在创建单元测试用例时无法将@Autowired与@Mock一起使用

时间:2017-06-07 12:39:16

标签: java unit-testing spring-boot mockito

我有一个服务说MainService,它的管理员很少用@Autowired进行初始化,而且它使用的是一些外部服务@Autowired

我的目的是创建单元测试用例,以便我可以与管理员一起访问内存数据库,并且想要模拟外部服务。

现在我面临的问题是,如果我在单元测试中使用@Autowired并使用@Mock作为外部服务,那么它不使用模拟方法,而是使用实际的实现。如果我@InjectMocks那么它不会从repo中选择数据,因为它没有找到管理员的相应依赖关系,如果我一起使用@Autowired@InjectMocks它仍然不存在能够使用模拟。

像这样的东西

@Service
public class MainService extends AbstractService
{
  @Autowired
  Manager1 manager1;

  @Autowired
  Manager2 manager2;

  @Autowired
  Manager3 manager3;

@Trace(dispatcher = true)
public void mainMethod(int data)
{
 int data1 = manager1.getData(int xyz);\\ getting data from DAO
 int data2 = manager1.getData(int xyz);\\ getting data from DAO
 int data3 = manager1.getData(int xyz);\\ getting data from 
                                        \\External Service
    }

  }

现在我正在编写的测试用例是

@RunWith(SpringRunner.class)
@ActiveProfiles("test")
public class TestClass {

  @InjectMocks
  @Autowired  
  MainService service;

  @Autowired
  RepoForManager1 repoManager1;

  @Autowired
  RepoForManager2 repoManager2;

  @Mock
  Manager3 manager3;

  @Before
  public void initTest()
  {
      MockitoAnnotations.initMocks(this);
      int dataFirst=1;
      int dataSecond =2;
      int dataThird=3;
      int dataForMethod=4;
      repoManager1.save(dataFirst); 
      repoManager2.save(dataSecond);
     }

   @Test
      public void testMethod()
      { 

         Mockito.when(manager3.getData(Mockito.anyInt())).thenReturn(dataThird);
         service.mainMethod(dataForMethod);
       }
 }

这是实际服务的复制,当我调试测试时发现模拟没有被使用,它使用实际的实现,当我从@Autowired删除MainService时它只执行模拟方法。

2 个答案:

答案 0 :(得分:0)

如果您想使用Mockito,则需要使用TestClass而非@RunWith(MockitoJUnitRunner.class)注释@RunWith(SpringRunner.class)

然后@AutoWired TestClass repoManager1中的repoManger2@Mock。使用@Autowired而不是@ActiveProfiles("test")对其进行注释,因为您想使用Mockito来模拟它们。

我自己没有使用SpringRunner,但是通过快速阅读,我可以看到它主要用于集成测试,你想要加载SpringContext..etc。

此外,// Add image from local var canvas = new fabric.Canvas('c'); // display/hide controls on double click fabric.util.addListener(canvas.upperCanvasEl, 'dblclick', function(e) { if (canvas.findTarget(e)) { let objType = canvas.findTarget(e).type; if (objType === 'i-text') { document.getElementById('textControls').hidden = false; } } }); canvas.on('before:selection:cleared', function(e) { document.getElementById('trash').hidden = true; document.getElementById('forward').hidden = true; document.getElementById('back').hidden = true; if (e.target.type === 'i-text') { document.getElementById('textControls').hidden = true; } }); document.getElementById('file').addEventListener("change", function(e) { var file = e.target.files[0]; var reader = new FileReader(); reader.onload = function(f) { var data = f.target.result; fabric.Image.fromURL(data, function(img) { var oImg = img.set({ left: 0, top: 0, angle: 00, stroke: '#F0F0F0', //<-- set this strokeWidth: 40 //<-- set this }).scale(0.2); canvas.add(oImg).renderAll(); //var a = canvas.setActiveObject(oImg); var dataURL = canvas.toDataURL({ format: 'png', quality: 1 }); }); }; reader.readAsDataURL(file); }); // Delete selected object window.deleteObject = function() { canvas.getActiveObject().remove(); } // Refresh page function refresh() { setTimeout(function() { location.reload() }, 100); } // Add text function Addtext() { canvas.add(new fabric.IText('Tap and Type', { left: 50, top: 100, fontFamily: 'helvetica neue', fill: '#333', stroke: '#F0F0F0', strokeWidth: 1, fontSize: 45 })); } document.getElementById('text-color').onchange = function() { canvas.getActiveObject().setFill(this.value); canvas.renderAll(); }; document.getElementById('text-color').onchange = function() { canvas.getActiveObject().setFill(this.value); canvas.renderAll(); }; document.getElementById('text-bg-color').onchange = function() { canvas.getActiveObject().setBackgroundColor(this.value); canvas.renderAll(); }; document.getElementById('text-lines-bg-color').onchange = function() { canvas.getActiveObject().setTextBackgroundColor(this.value); canvas.renderAll(); }; document.getElementById('text-stroke-color').onchange = function() { canvas.getActiveObject().setStroke(this.value); canvas.renderAll(); }; document.getElementById('text-stroke-width').onchange = function() { canvas.getActiveObject().setStrokeWidth(this.value); canvas.renderAll(); }; document.getElementById('font-family').onchange = function() { canvas.getActiveObject().setFontFamily(this.value); canvas.renderAll(); }; document.getElementById('text-font-size').onchange = function() { canvas.getActiveObject().setFontSize(this.value); canvas.renderAll(); }; document.getElementById('text-line-height').onchange = function() { canvas.getActiveObject().setLineHeight(this.value); canvas.renderAll(); }; document.getElementById('text-align').onchange = function() { canvas.getActiveObject().setTextAlign(this.value); canvas.renderAll(); }; radios5 = document.getElementsByName("fonttype"); // wijzig naar button for (var i = 0, max = radios5.length; i < max; i++) { radios5[i].onclick = function() { if (document.getElementById(this.id).checked == true) { if (this.id == "text-cmd-bold") { canvas.getActiveObject().set("fontWeight", "bold"); } if (this.id == "text-cmd-italic") { canvas.getActiveObject().set("fontStyle", "italic"); } if (this.id == "text-cmd-underline") { canvas.getActiveObject().set("textDecoration", "underline"); } if (this.id == "text-cmd-linethrough") { canvas.getActiveObject().set("textDecoration", "line-through"); } if (this.id == "text-cmd-overline") { canvas.getActiveObject().set("textDecoration", "overline"); } } else { if (this.id == "text-cmd-bold") { canvas.getActiveObject().set("fontWeight", ""); } if (this.id == "text-cmd-italic") { canvas.getActiveObject().set("fontStyle", ""); } if (this.id == "text-cmd-underline") { canvas.getActiveObject().set("textDecoration", ""); } if (this.id == "text-cmd-linethrough") { canvas.getActiveObject().set("textDecoration", ""); } if (this.id == "text-cmd-overline") { canvas.getActiveObject().set("textDecoration", ""); } } canvas.renderAll(); } } // Send selected object to front or back var selectedObject; canvas.on('object:selected', function(event) { selectedObject = event.target; }); var sendSelectedObjectBack = function() { canvas.sendToBack(selectedObject); } var sendSelectedObjectToFront = function() { canvas.bringToFront(selectedObject); }主要用于集成测试,您可以使用&#39; test&#39;来加载弹簧上下文。档案属性。

答案 1 :(得分:0)

使用构造函数注入,而不是使用字段注入(在类变量上使用@Autowired)。这样,您可以使用一些模拟和一些真正的实现来初始化MainService类。像这样的东西

    @Service
    public class MainService extends AbstractService
    {

      private final Manager1 manager1;

      private final Manager2 manager2;

      private final SomeExternalService externalService;

       @Autowired
       public MainService(Manager1 manager1, Manager2 manager2, SomeExternalService externalService) 

            this.manager1= manager1;
            this.manager2= manager2;
            this.externalService = externalService;
    }
            ........................
   }

从您的测试类中不要使用Autowire MainService。只需Autowire Manager1和Manager2以及为SomeExternalService创建模拟(并初始化它)。然后使用构造函数创建MainService实例。

    public class TestClass {

          MainService service;

          @Autowired
          RepoForManager1 repoManager1;

          @Autowired
          RepoForManager2 repoManager2;

          @Mock
          SomeExternalService externalService;

          @Before
          public void setUp(){
           service = new MainService(repoManager1, repoManager2, externalService);
          }
   }