英文:
What is the alternative to autowiring while running a class through testNG?
问题
我正在验证ABCValidatorTest.java中的testValidateABC()方法。
ABCValidatorTest.java
public class ABCValidatorTest {
@Test
public void testValidateABC() {
ABCValidator validator = new ABCValidator();
List<String> input = Arrays.asList("0", "1234", "abcd");
List<Boolean> expectedOutput = Arrays.asList(false, true, false);
boolean output;
for (int i = 0; i < input.size(); i++) {
if (StringUtils.isNotEmpty(input.get(i))) {
output = validator.validateABC(input.get(i));
} else {
output = false;
}
Assert.assertEquals((boolean) expectedOutput.get(i), output);
}
}
}
这里我创建了一个ABCValidator的对象,下面是它的类定义:
ABCValidator.java
public class ABCValidator {
@Autowired(required = false)
private ABCSearch abcRestClient;
public boolean validateABC(String abc_code) {
String response = abcRestClient.searchABCCodes(abc_code);
boolean hasValidabc = true;
if ((response.startsWith("null", 1)) || (response.equals("[]"))) {
hasValidabc = false;
}
return hasValidabc;
}
}
在这里,我使用@Autowired注入了ABCSearch以获取searchABCCodes()方法。
当我运行这段代码时,由于abcRestClient未初始化,我得到了一个NullPointerException。我如何在不更改ABCValidator.java中的任何内容的情况下修复这个问题?
英文:
I am validating the method testValidateABC() in ABCValidatorTest.java
ABCValidatorTest.java
public class ABCValidatorTest {
@Test
public void testValidateABC() {
ABCValidator validator = new ABCValidator();
List<String> input = Arrays.asList("0", "1234", "abcd");
List<Boolean> expectedOutput = Arrays.asList(false, true, false);
boolean output;
for (int i = 0; i < input.size(); i++) {
if (StringUtils.isNotEmpty(input.get(i))) {
output = validator.validateABC(input.get(i));
} else {
output = false;
}
Assert.assertEquals((boolean) expectedOutput.get(i), output);
}
}
}
Here I am creating an object of ABCValidator and below is its class:
ABCValidator.java
public class ABCValidator {
@Autowired(required = false)
private ABCSearch abcRestClient;
public boolean validateABC(String abc_code) {
String response = abcRestClient.searchABCCodes(abc_code);
boolean hasValidabc = true;
if ((response.startsWith("null", 1)) || (response.equals("[]"))) {
hasValidabc = false;
}
return hasValidabc;
}
}
Here I have autowired ABCSearch to get the method searchABCCodes().
I am getting a NullPointerException when i run this since abcRestClient is not intitalized. How can I fix this without changing anything in ABCValidator.java?
答案1
得分: 1
清晰的解决方案是使用构造函数注入,而不是字段注入。(出于多种原因,包括可以防止几类错误,这是一个不错的想法。)
然后,您不需要任何特殊的Spring或反射支持,只需要一个普通的模拟对象:
@Test
public void testValidateABC() {
ABCSearch mockRestClient = Mockito.mock(ABCSearch.class);
ABCValidator validator = new ABCValidator(mockRestClient);
List<String> input = Arrays.asList("0", "1234", "abcd");
List<Boolean> expectedOutput = Arrays.asList(false, true, false);
for (int i = 0; i < input.size(); i++) {
when(mockRestClient.searchABCCodes(input.get(i))).thenReturn(/* 正确的布尔值 */);
Assert.assertEquals((boolean) expectedOutput.get(i), validator.validateABC(input.get(i)));
}
}
请注意,您在这里所做的是一个_参数化测试_;我对TestNG不是特别熟悉,但我预期它支持这种功能。我是 Spock 的粉丝(这是一个在JUnit之上运行的测试DSL),它可以让这种类型的测试非常清晰易读。
英文:
The clean answer is to use constructor injection instead of field injection. (This is a good idea for a number of reasons, including that it prevents several categories of bugs.)
Then you don't need any special Spring or reflection support, just a normal mock:
@Test
public void testValidateABC() {
ABCSearch mockRestClient = Mockito.mock(ABCSearch.class);
ABCValidator validator = new ABCValidator(mockRestClient);
List<String> input = Arrays.asList("0", "1234", "abcd");
List<Boolean> expectedOutput = Arrays.asList(false, true, false);
for (int i = 0; i < input.size(); i++) {
when(mockRestClient.searchABCCodes(input.get(i)).thenReturn(/* the correct boolean */);
Assert.assertEquals((boolean) expectedOutput.get(i), validator.validateABC(input.get(i)));
}
}
Note that what you're doing here is called a parameterized test; I'm not especially familiar with TestNG but expect there is support for it. I am a fan of Spock (a test DSL that runs on top of JUnit) that makes this kind of test very clean.
答案2
得分: 0
@RunWith(MockitoRunner.class)
public class ABCValidatorTest {
@Mock
private ABCSearch search;
@DataProvider(name = "dataSet")
public static Object[][] createdataSet() {
return new Object[][] { { "one", true }, { "three", true }, { "four", true }, { "five", true }, };
}
@Test(dataProvider = "dataSet")
public void testValidateABC(String input, Boolean expectedResult) {
ABCValidator validator = new ABCValidator();
Whitebox.setInternalState(validator, "abcRestClient", search);
output = validator.validateABC(input);
Assert.assertEquals(expectedResult, output);
}
}
英文:
If you want to write a unit test you can use Mocktio and parameterized test in Testng
@RunWith(MockitoRunner.class)
public class ABCValidatorTest {
@Mock
private ABCSearch search;
@DataProvider(name = "dataSet")
public static Object[][] createdataSet() {
return new Object[][] { { "one", true }, { "three", true }, { "four", true }, { "five", true }, };
}
@Test(dataProvider = "dataSet")
public void testValidateABC(String input, Boolean expectedResult) {
ABCValidator validator = new ABCValidator();
Whitebox.setInternalState(validator, "abcRestClient", search);
output = validator.validateABC(input);
Assert.assertEquals(expectedResult, output);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论