TDD how to handle a change in a mocked object

后端 未结 4 1177
孤街浪徒
孤街浪徒 2021-02-13 02:32

In writing unit tests, for each object that the unit interacts with, I am taking these steps (stolen from my understanding of JBrains\' Integration Tests are a Scam):

4条回答
  •  名媛妹妹
    2021-02-13 02:43

    First, it's definitely harder to get this level of coverage with integration tests, so I think unit tests are still superior. However, I think you have a point. It's hard to keep your objects' behavior in sync.

    An answer to this is to have partial integration tests that have real services 1 level deep, but beyond that are mocks. For instance:

    var sut = new SubjectUnderTest(new Service1(Mock.Of(), ...), ...);
    

    This solves the problem of keeping behaviors in sync, but compounds the level of complexity because you now have to setup many more mocks.

    You can solve this problem in a functional programming language using discriminated unions. For instance:

    // discriminated union
    type ResponseType
    | Success
    | Fail of string   // takes an argument of type string
    
    // a function
    let saveObject x =
        if x = "" then
            Fail "argument was empty"
        else
            // do something
            Success
    
    let result = saveObject arg 
    
    // handle response types
    match result with
    | Success -> printf "success"
    | Fail msg -> printf "Failure: %s" msg
    

    You define a discriminated union called ResponseType that has a number of possible states, some of which can take arguments and other metadata. Every time you access a return value you have to deal with possible various conditions. If you were to add another failure type or success type, the compiler would give you warnings for each time you don't handle the new member.

    This concept can go a long way toward handling the evolution of a program. C#, Java, Ruby and other languages use exceptions to communicate failure conditions. But these failure conditions are frequently not "exceptional" circumstances at all, which ends up leading to the situation you are dealing with.

    I think functional languages are the closest to providing the best answer to your question. Frankly, I don't think there is a perfect answer, or even a good answer in many languages. But compile-time checking can go a long way

提交回复
热议问题