我正在使用RestTemplate postForEntity
方法将正文发布到端点。我需要使用Mockito编写代码测试用例的帮助。返回类型为void,但是如果需要测试,可以将其更改为Types
或code
。我引用了许多其他文档,但是它们非常笼统,我尝试使用它们,但是由于request
和返回类型不同,大多数文档对我来说都不起作用。 。任何建议表示赞赏。谢谢
这是我的Java课堂
public void postJson(Set<Type> Types){
try {
String oneString = String.join(",", Types);
Map<String, String> requestBody = new HashMap<>();
requestBody.put("type", oneString);
requestBody.put("data", "aws");
JSONObject jsonObject = new JSONObject(requestBody);
HttpEntity<String> request = new HttpEntity<String>(jsonObject.toString(), null);
MappingJackson2HttpMessageConverter jsonConvertor = new MappingJackson2HttpMessageConverter();
restTemplate.getMessageConverters().add(jsonConvertor);
StringHttpMessageConverter stringConvertor = new StringHttpMessageConverter();
restTemplate.getMessageConverters().add(stringConvertor);
ResponseEntity result = restTemplate.postForEntity(url, new HttpEntity<>(request, getHttpHeaders()), String.class);
int code = (int) result.getcodeValue();
}
}
private HttpEntity getHttpEntity() {
return new HttpEntity<>(null, getHttpHeaders());
}
public HttpHeaders getHttpHeaders() {
return headersBuilder.build();
}
}
前一段时间,我写了关于unit testing and test doubles的文章。您可以阅读如何进行单元测试的起点。
其中一些关键要点是:
由于缺少许多信息,因此很难编写整个测试。例如。什么是Type
。由于您没有发布课程的名称,因此暂时将其命名为MyClass
。我也假设RestTemplate是通过类似
MyClass(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
以下是使用JUnit 5和Mockito进行单元测试的草案。我建议嘲笑RestTemplate
。我必须承认,这样一来,我们将不会涵盖测试测试中MappingJackson2HttpMessageConverter
和StringHttpMessageConverter
的用法。
所以非常原始的草稿可能看起来像这样
import java.util.ArrayList;
import java.util.Set;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.springframework.http.HttpEntity;
import org.springframework.web.client.RestTemplate;
class MyClassTest {
private RestTemplate restTemplate;
private MyClass myClass;
@BeforeEach
void setUp() {
restTemplate = Mockito.mock(RestTemplate.class);
myClass = new MyClass(restTemplate);
}
@Test
void callMethod() {
Set<Type> types = Set.of(/* one of your Types */);
String url = "http://someUrl";
String httpResult = "";
Mockito.when(restTemplate.getMessageConverters()).thenReturn(new ArrayList<>());
ArgumentCaptor<HttpEntity> request = ArgumentCaptor.forClass(HttpEntity.class);
Mockito.when(restTemplate.postForObject(url, request.capture(), String.class)).thenReturn(httpResult);
myClass.callMethod(types, url);
HttpEntity<String> actualHttpEntity = request.getValue();
Assert.assertEquals(actualHttpEntity.getBody(), "");
}
}
问题中的代码违反了Single responsibility principle。作为结果之一,很难用单元测试来覆盖它。
如果很难编写测试,则代码设计不好。
问题中的班级可以重构为3个班级,职责更少。
java.util.function.Predicate
方法中的java.util.function.Predicate
的[filter
checkType
使用TypeChecker
方法注入了checkType
Predicate
用PlanRepo
方法注入postJson
和TypeChecker
的方法重构示例:
RestTemplate
通过这种方式,可以使用@Component
public class TypePredicate implements Predicate<Type> {
boolean test(Type mark) {
return a.getValue().equals(mark)
|| b.getValue().equals(mark)
|| c.getValue().equals(mark);
}
}
@Component
public class TypeChecker {
private final TypePredicate typePredicate;
/* constructor */
public Set<String> checkType(Set<Type> types) {
return types.stream()
.filter(typePredicate)
//...
.collect(Collectors.toSet());
}
}
@Component
public class PlanRepo {
private final TypeChecker typeChecker;
private final RestTemplate restTemplate;
private final String url;
/* constructor */
public Set<String> postJson(Set<Type> types) {
Set<Type> finalValue = typeChecker.checkTypes(types);
//...
//restTemplate.postForObject(url, request, String.class);
//...
}
}
轻松创建单元测试。
Mockito
此单元测试将涵盖谓词的所有情况,因此其他类的测试无需检查它。只是嘲笑谓词。
@RunWith(MockitoJUnitRunner.class)
public class TypePredicateTest {
@Mock
private Type mockType;
private final TypePredicate typePredicate = new TypePredicate();
@Test
public void testSomething() {
when(mockType.getValue()).thenReturn("something"); //define the behaviour for the mock
assertThat(typePredicate.test(mockType)).isTrue(); //AssertJ fluent assertions for Java
}
@Test
public void testSomethingElse() {
when(mockType.getValue()).thenReturn("something else");
assertThat(typePredicate.test(mockType)).isFalse();
}
}
@RunWith(MockitoJUnitRunner.class)
public class TypeCheckerTest {
@Mock
private TypePredicate typePredicate;
@InjectMocks
private TypeChecker typeChecker;
@Test
public void test() {
Set<Type> types = Set.of(/*...*/);
assertThat(typeChecker.checkType(types)).contains(/*type1, type2, ...*/);
verify(typePredicate, times(3)).test(any(Type.class)); //verify that the mock was executed desired number of times
}
}
相同。可以对其进行模拟和验证。
RestTemplate
以下幻灯片可能有用@RunWith(MockitoJUnitRunner.class)
public class PlanRepoTest {
@Mock
private TypeChecker typeChecker;
@Mock
private RestTemplate restTemplate;
private PlanRepo planRepo;
@Before
public void setUp() {
planRepo = new PlanRepo(typeChecker, restTemplate, "http://example.com");
}
@Test
public void test() {
when(typeChecker.checkType(any(Set.class))).thenReturn(Set.of(/*...*/));
//...
//assertThat(planRepo.postJson(...)).contains(...)
//verify(restTemplate).postForObject(eq("http://example.com"), ...)
}
}