Как проверить, что другой метод в классе был вызван с помощью Moq - PullRequest
15 голосов
/ 13 сентября 2009

Это кажется чем-то простым, но я не могу заставить его работать.

У меня есть класс с методом Save, который просто вызывает другой метод ShouldBeCalled (). Я хочу убедиться, что если я вызову Save (), то другой метод ShouldBeCalled () будет выполнен хотя бы один раз. Я думал, что смогу сделать следующее.

public class ClassA
{
    public virtual void Save()
    {
        ShouldBeCalled();
    }

    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        var mockClassA = new Mock<ClassA>();
        mockClassA.Object.Save();

        mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
    }
}

Но я получаю исключение "Ожидаемый вызов на макет хотя бы один раз, но никогда не выполнялся: x => x.ShouldBeCalled ()"

Это только предположение, но Moq переопределяет метод Save () своей собственной версией, которая игнорирует все, что у меня есть внутри метода Save () реального объекта.

Ответы [ 4 ]

29 голосов
/ 13 сентября 2009

У вас возникла эта проблема, потому что вы издеваетесь над тем, что тестируете. Это не имеет смысла.

Вы правы, что Moq заменит реализацию вашего метода своей собственной. Причина в том, что вы должны использовать Moq для насмешки над классом , который вы тестируете , а не над классом, который вы тестируете сами.

Этот тест был бы уместен, если бы ваш код был разработан таким образом:

public class ClassA
{
    BusinessLogicClass bl;
    public ClassA(BusinessLogicClass bl)
    {
         this.bl = bl;
    }

    public void Save()
    {
        bl.ShouldBeCalled();
    }
}

public class BusinessLogicClass
{
    public virtual void ShouldBeCalled()
    {
        //This should get executed
    }
}

И вот правильный тест этого метода сейчас:

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_ShouldCallShouldBeCalled()
    {
        //Arrange
        var mockBLClass = new Mock<BusinessLogicClass>();
        mockBLClass.Setup(x => x.ShouldBeCalled()).Verifyable();

        //Act    
        ClassA classA = new ClassA(mockBLClass.Object);
        classA.Save();

        //Assert
        mockBLClass.VerifyAll();
    }
}

Ключевым уроком здесь является то, что вы имитируете / заглушаете то, что нужно для выполнения теста , а не то, что вы тестируете сами.

Надеюсь, это поможет, Anderson

4 голосов
/ 26 октября 2011

Попробуйте использовать CallBase = true, а затем false. Я запустил твой код, и он работает.

var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true;
mockClassA.Object.Save();
mockClassA.CallBase = false;
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
2 голосов
/ 13 сентября 2009

Да, это можно сделать. Однако вам нужно добавить строку кода, чтобы Moq отслеживал, действительно ли был вызван метод ShouldBeCalled.

Будет работать что-то вроде следующего:

var mockClassA = new Mock<ClassA>();
mockClassA.Setup(x => x.ShouldBeCalled()).Verifiable();    
mockClassA.Object.Save();    
mockClassA.Verify(x => s.ShouldBeCalled(), Times.AtLeastOnce());

Метод установки устанавливает ожидания. Когда вы звоните в Verify, вы просите Moq проверить эти ожидания. Если вы не сделаете вызов Setup для создания ожиданий для метода ShouldBeCalled, то Moq не сочтет его отслеживаемым и поэтому потерпит неудачу при попытке его проверить.

1 голос
/ 25 июня 2013

Вы можете заблокировать методы в тестируемой системе, используя CallBase.

[TestFixture]
public class ClassA_Test
{
    [Test]
    public void Save_Should_Call_ShouldBeCalled()
    {
        // Arrange
        var mockClassA = new Mock<ClassA>();
        mockClassA.CallBase = true; // this will call real methods unless the method is mocked/stubbed. 
        mockClassA.Setup(a => a.ShouldBeCalled());

        // Act
        mockClassA.Save();

        // Assert
        mockClassA.Verify(a => a.ShouldBeCalled(), Times.Once());
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...