Moq ile bir yöntemin tam olarak bir kez çağrıldığını nasıl doğrularım? Verify()
Vs Verifable()
olayı gerçekten kafa karıştırıcı.
Moq ile bir yöntemin tam olarak bir kez çağrıldığını nasıl doğrularım? Verify()
Vs Verifable()
olayı gerçekten kafa karıştırıcı.
Yanıtlar:
Sen kullanabilirsiniz Times.Once()
veya Times.Exactly(1)
:
mockContext.Verify(x => x.SaveChanges(), Times.Once());
mockContext.Verify(x => x.SaveChanges(), Times.Exactly(1));
İşte Times sınıfındaki yöntemler :
AtLeast
- Sahte bir yöntemin en az kez çağrılması gerektiğini belirtir.AtLeastOnce
- Sahte bir yöntemin en az bir kez çağrılması gerektiğini belirtir.AtMost
- Sahte bir yöntemin maksimum süre olarak çağrılması gerektiğini belirtir.AtMostOnce
- Sahte bir yöntemin en fazla bir kez çağrılması gerektiğini belirtir.Between
- Alay edilen bir yöntemin from ve to times arasında çağrılması gerektiğini belirtir.Exactly
- Alay edilen bir yöntemin tam olarak kez çağrılması gerektiğini belirtir.Never
- Sahte bir yöntemin çağrılmaması gerektiğini belirtir.Once
- Alay edilen bir yöntemin tam olarak bir kez çağrılması gerektiğini belirtir.Sadece bunların yöntem çağrıları olduğunu unutmayın; Onların mülk olduğunu düşünerek ve parantezleri unutarak takılmaya devam ettim.
var mockContext = new Mock<IContext>()
ayarlamak gibi bir şeydi .
AtLeast
, AtMost
, Between
, veya Exactly
mülk olarak görülebilir. Demek istediğim, bir şey yapmak için bir parametreye ihtiyaçları var.
2 tamsayı eklemek için bir yöntemle bir hesap makinesi oluşturduğumuzu hayal edin. İhtiyacın, add yöntemi çağrıldığında, print yöntemini bir kez çağırdığını hayal edelim. İşte bunu nasıl test edeceğimiz:
public interface IPrinter
{
void Print(int answer);
}
public class ConsolePrinter : IPrinter
{
public void Print(int answer)
{
Console.WriteLine("The answer is {0}.", answer);
}
}
public class Calculator
{
private IPrinter printer;
public Calculator(IPrinter printer)
{
this.printer = printer;
}
public void Add(int num1, int num2)
{
printer.Print(num1 + num2);
}
}
Ve burada daha fazla açıklama için kod içinde yorumların bulunduğu gerçek test var:
[TestClass]
public class CalculatorTests
{
[TestMethod]
public void WhenAddIsCalled__ItShouldCallPrint()
{
/* Arrange */
var iPrinterMock = new Mock<IPrinter>();
// Let's mock the method so when it is called, we handle it
iPrinterMock.Setup(x => x.Print(It.IsAny<int>()));
// Create the calculator and pass the mocked printer to it
var calculator = new Calculator(iPrinterMock.Object);
/* Act */
calculator.Add(1, 1);
/* Assert */
// Let's make sure that the calculator's Add method called printer.Print. Here we are making sure it is called once but this is optional
iPrinterMock.Verify(x => x.Print(It.IsAny<int>()), Times.Once);
// Or we can be more specific and ensure that Print was called with the correct parameter.
iPrinterMock.Verify(x => x.Print(3), Times.Once);
}
}
Not : Varsayılan olarak Moq, siz bir Mock nesnesi oluşturduğunuz anda tüm özellikleri ve yöntemleri saplayacaktır. Böylece, arama Setup
yapmasanız bile , Moq yöntemlerini çoktan başlattı, IPrinter
böylece sadece arayabilirsiniz Verify
. Bununla birlikte, iyi bir uygulama olarak, her zaman bunu kurarım çünkü belirli beklentileri karşılamak için metoda parametreleri veya belirli beklentileri karşılamak için metottan elde edilen dönüş değerini veya kaç kez çağrıldığını zorlamamız gerekebilir.
Verify
, Times.Once
hiç uğramadan Setup
. Verify
Bu durumda kesinlikle patlamayı beklerdim , ama olmadı.
Mock
nesne yaratır oluşturmaz tüm özellikleri ve yöntemleri saplayacaktır . Böylece, arama Setup
yapmasanız bile , Moq yöntemlerini çoktan başlattı, IPrinter
böylece sadece arayabilirsiniz Verify
. Bununla birlikte, iyi bir uygulama olarak, her zaman ayarladım çünkü parametreleri yönteme veya yöntemden dönüş değerini zorlamamız gerekebilir.
Times.Exactly(1)
ve yöntem aslında iki kez çağrıldığında başarısız olmadı . Ancak Setup
söz konusu yöntem için eklendikten sonra doğru şekilde başarısız oldu.
Test kontrolörü şunlar olabilir:
public HttpResponseMessage DeleteCars(HttpRequestMessage request, int id)
{
Car item = _service.Get(id);
if (item == null)
{
return request.CreateResponse(HttpStatusCode.NotFound);
}
_service.Remove(id);
return request.CreateResponse(HttpStatusCode.OK);
}
DeleteCars yöntemi geçerli bir id ile çağrıldığında, bu test tarafından tam olarak bir kez çağrılan Service remove yöntemini doğrulayabiliriz:
[TestMethod]
public void Delete_WhenInvokedWithValidId_ShouldBeCalledRevomeOnce()
{
//arange
const int carid = 10;
var car = new Car() { Id = carid, Year = 2001, Model = "TTT", Make = "CAR 1", Price=2000 };
mockCarService.Setup(x => x.Get(It.IsAny<int>())).Returns(car);
var httpRequestMessage = new HttpRequestMessage();
httpRequestMessage.Properties[HttpPropertyKeys.HttpConfigurationKey] = new HttpConfiguration();
//act
var result = carController.DeleteCar(httpRequestMessage, vechileId);
//assert
mockCarService.Verify(x => x.Remove(carid), Times.Exactly(1));
}