简体   繁体   中英

Nsubstitute testing if a private class's method was called

Don't have much experience with testing, trying to change that by testing libraries I've made recently.

Using nunit with nsubstitute for this.

So the situation I have is a class like this:

class MyClassToTest {
    private ISomeOtherClass MyPrivateClass { get;set }

    public MyClassToTest() {
        MyPrivateClass = new SomeOtherClass();
    }

    public void DoSomething() {
        MyPrivateClass.SayHello();
    }
} 

Now, a test for the DoSomething method would be to see if the method SayHello() was actually called on the ISomeOtherClass instance.

The problem is that it's private, when looking up the best way to test this, the only thing that came up was to make the property internal and set the InternalsVisibleToAttribute to the assembly the tests are in.

While this solution works and the external interface for my library is still ok, the correct accessor for this property in the context of the library would still be private.

The test I'd write is after making it interal:

public void MyTest() {
    var objPrivateClass = Substitute.For<ISomeOtherClass>();

    var obj = new MyClassToTest();
    obj.MyPrivateClass = objPrivateClass;
    obj.DoSomething();


    objPrivateClass.Received().SayHello();
}

Is there a better way to test this without me having to modify my original code to make it testable?

It might be setting InternalsVisibleToAttribute and making the property internal is the correct thing here, but a couple of hours ago I didn't know about the existence of InternalsVisibleToAttribute so thought it best to ask :)

To answer the exact question, You can use reflection to reach private members, but that is a fragile and rather slow solution.

The best advice I can give you is that private things should stay private; test an object's behavior through its public interface . So if is too big and hard to test, just refactor it to be testable. Think of the Single Responsibility Principle and the Inversion of Control principles.

Edit 1.: You are probably looking for the concept of Dependency Injection . This should be alright most of the times; however when we talk about highly reusable libraries (you mentioned you are making a lib), other solutions may fit better for the users of your library (eg creating a Facade or rethinking your design).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM