UnitTest辅助类(不是控制器,不是服务,
一开始我需要说我读了很多帖子,例如: When should I mock? 要么 Should I mock all the dependencies when unit testing?
我还阅读了一篇关于"如何在SPRING中测试控制器的文章"或"如何测试服务层"。
但是现在我想测试一个" Helper类"对于我的"控制器" (我不确定是否存在差异)。
我的实体类看起来像这样:
topics 1:n posts 1:n comments 1:n time.
让我们看看我想测试的方法:
void parseToModel(Map<Integer, TimeForm> mapToTime, Time time) {
mapToTime.putIfAbsent(time.getComment().getId(), new TimeForm(time.getComment().getPost().getTopic().getName(),
time.getComment().getPost().getName(),
time.getComment().getName(),
new ArrayList<>()));
}
就像你注意到这里方法有两个参数,一个是map(Integer和TimeForm)和时间。
这意味着要进行此测试,我需要创建Time的testObject,我需要在该方法中设置所有字段? e.g。
Time time = new Time();
time.getComment().setId();
time.getComment().getPost().getTopic().setName();
time.getComment().getPost().setName();
time.getComment().setName();
return time;
就像你可以注意到时间需要评论,评论需要一个帖子,帖子需要一个主题。 这意味着我需要创建所有这些? 你能解释一下我做错了吗?
@RunWith(MockitoJUnitRunner.class)
public class helperTest{
//given
final TimeController timeController = new TimeController(Mockito.mock(TimeService.class));
Map<Integer, TimeForm> testMap = new HashMap<>();
Time testObject = generateSimpleTestObject();
@Test
public void parse() {
//when
timeController.parseToModel(testMap, testObject);
//then
Assert.assertEquals(testMap.size(), 1);
}
Time generateTestObj(){
Time testObj = new Time();
time.getComment().setId("5");
time.getComment().getPost().getTopic().setName("TestingJava");
time.getComment().getPost().setName("Unit test.");
time.getComment().setName("Is it so hard?");
return time;
}
}
当我使用像upper这样的示例数据运行我的测试时,我有一个java.lang.NullPointerException。
这是一个错误堆栈跟踪:
java.lang.NullPointerException at com.timeproject.time.view.HelperTest.generateSimpleTestObject(HelperTest.java:40) 在com.timeproject.time.view.HelperTest。(HelperTest.java:26) at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native 方法)at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) at java.lang.reflect.Constructor.newInstance(Constructor.java:423) 在 org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:217) 在 org.junit.runners.BlockJUnit4ClassRunner $ 1.runReflectiveCall(BlockJUnit4ClassRunner.java:266) 在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) 在 org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) 在 org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) 在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)at at org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)at at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at at org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)at at org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)at at org.junit.runners.ParentRunner.run(ParentRunner.java:363)at at org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run(JUnit45AndHigherRunnerImpl.java:37) 在 org.mockito.runners.MockitoJUnitRunner.run(MockitoJUnitRunner.java:62) 在org.junit.runner.JUnitCore.run(JUnitCore.java:137)at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) 在 com.intellij.rt.execution.junit.IdeaTestRunner $ Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) 在 com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) 在 com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
更新: 在编辑我的testObject方法之后测试通过:
Time generateSimpleTimeTestObject() {
Time time = new Time();
Comment comment = new Comment();
Project project = new Project();
Topic topic = new Topic();
time.setComment(comment);
time.getComment().setPost(post);
time.getComment().getPost().setTopic(topic);
time.getComment().setId(999);
time.getComment().getPost().getTopic().setName("Topic name");
time.getComment().getPost().setName("Post name");
time.getComment().setName("Comment name");
return time;
}
但是我仍然不确定它是否是正确的方式(如果有人能够在评论中确认它是100%正确的方式,我会感激不尽。)
答案 0 :(得分:1)
这意味着我需要创建所有这些?
是
你能解释一下我做错了吗?
概念性?什么都没有。
您的参数Time
看起来像数据传输对象。这有点特殊,所以我们通常不会将demeter的定律(不要与陌生人交谈!)应用于他们。
另一方面,您可能希望隐藏信息隐藏(并因此 LoD ,以便您通过添加来避免&#34;链破坏&#34; 委派方法到Time
类。
然后Time
有点像&#34; hybrit&#34;你会创建一个它的模拟(它不会为&#34;纯&#34; DTO而做,并且不需要配置Time
对象的所有依赖...