如何在测试时将模拟对象注入类中?

时间:2018-01-15 04:10:44

标签: java unit-testing mockito

我的用户类如下,

Option Explicit

Sub Parse_any_delimited( _
    Optional ByVal dlm_pipe As Boolean = False, _
    Optional ByVal dlm_semi As Boolean = False, _
    Optional ByVal dlm_comma As Boolean = False, _
    Optional ByVal dlm_tab As Boolean = False, _
    Optional ByVal dlm_carat As Boolean = False, _
    Optional ByVal dlm_char As String = "", _
    Optional ByVal no_delim_popup As Boolean = True)


' *** WARNING !!! ***
'
' The FIRST record that EXCEL will see DURING AN IMPORT CANNOT CONTAIN
' COMMAS! IF IT DOES, it interprets those as DELIMITERS and AUTOMATICALLY
' does a field split there BEFORE running any code!  The result is that
' when all text SHOULD wind up in Cell A1, instead it gets parsed into
' cells at each comma.  Then the REAL PARSE routine can only parse what
' IS in the Column A cells.
'
' The "comma parse" UPON LOADING occurs BEFORE any macro runs!

    Dim i As Integer
    Dim check_data As Boolean
        check_data = False

    Dim dlm_other As Boolean
        dlm_other = False
    Dim rcrd As Variant
    Dim leave_for As Boolean
    Dim have_delim As Boolean


'1 ****
    If dlm_pipe Then
        dlm_other = True
        dlm_char = "|"
        have_delim = True

'2 ****
    ElseIf dlm_carat Then
        dlm_other = True
        dlm_char = "^"
        have_delim = True

'3 ****
    ElseIf dlm_tab Or dlm_semi Or dlm_comma Then
         have_delim = True

'4 ****
    Else
        For i = 1 To 5  'Check first 5 records for common delimiters
            leave_for = True
            rcrd = Cells(i, "A").Value

            If Count_Characters(rcrd, "|") > 5 Then
                dlm_other = True
                dlm_char = "|"

            ElseIf Count_Characters(rcrd, ";") > 5 Then
                dlm_semi = True

            ElseIf Count_Characters(rcrd, ",") > 10 Then
                dlm_comma = True

            ElseIf Count_Characters(rcrd, vbTab) > 4 Then
                dlm_tab = True

            ElseIf Count_Characters(rcrd, "^") > 5 Then
                dlm_other = True
                dlm_char = "^"

            Else
                leave_for = False
            End If

      '===============
            If leave_for Then
                have_delim = True
                Exit For
            Else
                have_delim = False
            End If

        Next i

'5 ****
    End If

    If have_delim = False Then
        ' B2 is checked because in certain cases Excel will
        ' AUTOMATICALLY parse data delimited by | or semicolons.
        ' When that happens, THIS sub sees it as "No delimiter Can't Parse"
        ' even though it HAS BEEN parsed.
        If Cells(2, "B").Value = "" And no_delim_popup Then
            MsgBox ("CAN'T PARSE - NO DELIMITER FOUND")
        End If

        Exit Sub
    End If

    ' Stops "There's already data here--continue?"
    Application.DisplayAlerts = False

    Columns("A:A").Select
    Selection.TextToColumns _
        Destination:=Range("A1"), _
        DataType:=xlDelimited, _
        TextQualifier:=xlDoubleQuote, _
        ConsecutiveDelimiter:=False, _
            Tab:=dlm_tab, _
            Semicolon:=dlm_semi, _
            Comma:=dlm_comma, _
            Space:=False, _
            Other:=dlm_other, _
            OtherChar:=dlm_char

    Cells.Select
    Selection.Columns.AutoFit
    Range("A1").Select

    Application.DisplayAlerts = True

' Sub Parse_any_delimited()
End Sub


Function Count_Characters( _
    ByVal str As Variant, _
    ByVal chr As Variant) _
      As Long
    Count_Characters = Len(str) - Len(Replace(str, chr, ""))
End Function

我的测试课如下,

$('.side-menu').on('click', function(){
    $('.control-sidebar').toggleClass('active-sidebar');
});

正如您所看到的,应该将UserService对象注入UserResource类。如何在我的测试中将模拟UserService对象注入userResource对象?

仅供参考:

  • 这是Jersey JAX-RS项目的一部分。
  • 我正在使用Java CDI,mockito和testNG(作为测试库)。

2 个答案:

答案 0 :(得分:4)

考虑通过构造函数注入使用显式依赖主体,因为它非常清楚地说明了类执行其特定功能所需的内容。

public class UserResource {
  private UserService userService;

  @Inject
  public UserResource(UserService userService) {
    this.userService = userService;
  }

  public boolean createUser(User user) {
    DbResponse res = userService.addUser(user);
    if(res.isSuccess){
      return true;
    }else{
      return false;
    }
  }
}

并模拟UserService并将其分配给受测试的主题。配置测试的所需/模拟行为。

public class UserResourceTest {

  @Test
  public void test() {
    //Arrange
    boolean expected = true; 
    DbResponse mockResponse = mock(DbResponse.class);
    when(mockResponse.isSuccess).thenReturn(expected);

    User user = mock(User.class);
    UserService mockService = mock(UserService.class);
    when(mockService.addUser(user)).thenReturn(mockResponse);

    UserResource userResource = new UserResource(mockService);        

    //Act
    boolean actual = userResource.createUser(user);

    //Assert
    assert(expected == actual);
  }
}

答案 1 :(得分:2)

虽然我完全支持@Nkosi的答案,但我想将其添加为完整性:

使用Mockitos JUnitRule按照此处所述修改模拟:http://www.vogella.com/tutorials/Mockito/article.html

public class UserResourceTest {
    @Rule 
    public MockitoRule mockitoRule = MockitoJUnit.rule(); 
    @Mock
    private  DbResponse mockResponse;
    @Mock
    private UserService mockService;    

    @Test
    public void test() {
        //Arrange
        boolean expected = true; 
        when(mockResponse.isSuccess).thenReturn(expected);
        when(mockService.addUser(user)).thenReturn(mockResponse);
        // ...

此外,您还可以使用Mockitos @InjectMocks注释:

public class UserResourceTest {
    @Rule 
    public MockitoRule mockitoRule = MockitoJUnit.rule(); 
    @Mock
    private  DbResponse mockResponse;
    @Mock
    private UserService mockService;
    @InjectMocks
    private UserResource userResource; // do not instantiate in test method
     // ...

但我个人会劝阻

是的,它更方便,因为它通过 reflection 确定您使用的依赖注入方法。但是如果你没有“接缝”来注入某个依赖关系( Costructor参数非最终属性或匹配类型的 setter )你没有得到我个人觉得有问题的编译错误。