how can I use NSubstitute for stub and mock? any difference about the usage?

how can I use NSubstitute for stub and mock? any difference about the usage?

NSubstitute is a popular mocking library for .NET that allows you to create test doubles (stubs, mocks, etc.) for your dependencies in unit tests. The main difference between stubs and mocks is their purpose and how they are used in tests.

Stubs are used to provide predefined responses to method calls or property getters. They are typically used when you want to isolate the system under test (SUT) from its dependencies and control their behavior.

Mocks are used to verify that certain interactions occurred between the SUT and its dependencies. They are typically used when you want to ensure that the SUT is calling the correct methods or properties on its dependencies with the expected arguments.

Here's an example of how to use NSubstitute for creating a stub and a mock:

First, install the NSubstitute NuGet package:

Create an interface for the dependency you want to stub or mock:

public interface ICalculator
{
    int Add(int a, int b);
    int Multiply(int a, int b);
}

Use NSubstitute to create a stub:

using NSubstitute;

// ...

[Test]
public void TestAdditionWithStub()
{
    // Arrange
    var calculator = Substitute.For<ICalculator>();
    calculator.Add(1, 2).Returns(3);

    // Act
    int result = calculator.Add(1, 2);

    // Assert
    Assert.AreEqual(3, result);
}

Use NSubstitute to create a mock:

 

using NSubstitute;

// ...

[Test]
public void TestAdditionWithMock()
{
    // Arrange
    var calculator = Substitute.For<ICalculator>();

    // Act
    calculator.Add(1, 2);

    // Assert
    calculator.Received().Add(1, 2);
}

In the first example, we create a stub for the ICalculator interface and configure it to return 3 when the Add method is called with arguments 1 and 2.

In the second example, we create a mock for the ICalculator interface and use the Received() method to verify that the Add method was called with the expected arguments.

 

In summary, you can use NSubstitute to create both stubs and mocks depending on your testing needs.

Stubs are used to provide predefined responses to method calls or property getters, while mocks are used to verify that certain interactions occurred between the system under test (SUT) and its dependencies.

 

Here's another example to demonstrate the difference between stubs and mocks using NSubstitute:

Suppose you have a UserService class that depends on an IUserRepository interface for fetching user data:

public interface IUserRepository
{
    User GetUserById(int id);
    void SaveUser(User user);
}

public class UserService
{
    private readonly IUserRepository _userRepository;

    public UserService(IUserRepository userRepository)
    {
        _userRepository = userRepository;
    }

    public string GetUserName(int id)
    {
        var user = _userRepository.GetUserById(id);
        return user?.Name;
    }

    public void UpdateUserName(int id, string newName)
    {
        var user = _userRepository.GetUserById(id);
        if (user != null)
        {
            user.Name = newName;
            _userRepository.SaveUser(user);
        }
    }
}

Now, let's write tests for the GetUserName and UpdateUserName methods using stubs and mocks:

Create a stub for the IUserRepository interface to test the GetUserName method:

using NSubstitute;
using NUnit.Framework;

// ...

[Test]
public void TestGetUserNameWithStub()
{
    // Arrange
    var userRepository = Substitute.For<IUserRepository>();
    userRepository.GetUserById(1).Returns(new User { Id = 1, Name = "Alice" });

    var userService = new UserService(userRepository);

    // Act
    string userName = userService.GetUserName(1);

    // Assert
    Assert.AreEqual("Alice", userName);
}

In this test, we create a stub for the IUserRepository interface and configure it to return a User object with the name "Alice" when the GetUserById method is called with the argument 1.

 

Create a mock for the IUserRepository interface to test the UpdateUserName method:

using NSubstitute;
using NUnit.Framework;

// ...

[Test]
public void TestUpdateUserNameWithMock()
{
    // Arrange
    var userRepository = Substitute.For<IUserRepository>();
    userRepository.GetUserById(1).Returns(new User { Id = 1, Name = "Alice" });

    var userService = new UserService(userRepository);

    // Act
    userService.UpdateUserName(1, "Bob");

    // Assert
    userRepository.Received().GetUserById(1);
    userRepository.Received().SaveUser(Arg.Is<User>(user => user.Id == 1 && user.Name == "Bob"));
}

In these tests, we create stubs and mocks for the IUserRepository interface to test the GetUserName and UpdateUserName methods of the UserService class. 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章