0

I have a class called AuthManager. It implements an interface IAuthManager. The interface has two methods. AuthorizeTransaction() and CancelTransaction()

Let say I call AuthorizeTransaction() and it throws an exception, in the catch block I handle exception and call CancelTransaction().

How can I verify with Moq that my CancelTransaction() was called. I tried this with Mock mock = new Mock(). Then mock.Verify(…) to verify CancelTransaction() method was called. But I get error Non-override method cannot be verified. I don’t want to put virtual keyword on the method just so the test can pass. Is there anyway to verify CancelTransaction() was called upon exception? Thank you.

Update: I followed the link provided by Michael. This is my code below. But my testing is failing because of this error Expected invocation on the mock once, but was 0 times

            // Arrange
            mockAuth = new Mock<IAuthManager>();
            mockAuth.Setup(mock => mock.CancelAuthorization(It.IsAny<CancelAuthorizationModel>()));

            var auth = new AuthManager(new FakeDataRepo(), fakeDataManager, fakeCardManager(), fakeSearchManager, fakeTokenManager, new fakeConnection(), fakeDataManager);
            var authModel = GenerateModel(
                type: ...........,
                transactionType: ...........,
                transactionNumber: .........);

            try
            {
                // Act
                await auth.AuthorizeTransaction(authModel);
            }
            catch (Exception ex)
            {
                // Assert
                mockAuth.Verify(x => x.CancelTransaction(It.IsAny<CancelTransactionModel>()), Times.Once);
            }
  • Exactly which class do you want to test and which do you want to mock? – Klaus Gütter Mar 21 '23 at 07:22
  • AuthManager.cs is the class I want to test, it has two methods AuthorizeTransaction() and CancelTransaction(). I have class called AuthSpec.cs which has a test method. In that test method I want to verify when an exception is thrown in AuthorizeTransaction() method, CancelAuthorization() is called. – Gagandeep Singh Mar 21 '23 at 11:56
  • Do I get you right that the implementation class should call its own CancelAuthorization method whenever there is an exception in its own AuthorizeTransaction() method? This is a somewhat unusual design and hardly testable. – Klaus Gütter Mar 21 '23 at 19:50
  • The AuthorizeTransaction() has a try catch block, so if there is an exception, it calls CancelTransaction() method inside the catch block. I am working on existing code, it could have done better. There are lot of dependencies for the AuthManager.cs class as you can see in the constructor call. – Gagandeep Singh Mar 21 '23 at 19:55
  • Yes, but because it calls its own CancelTransaction() method you cannot verify by providing a mock. Except maybe by observing the actions CancelTransaction does on other (mockble) objects – Klaus Gütter Mar 21 '23 at 20:22
  • I see. Yes I don't see any way of proving that the CancelTransaction() method was called. I'll see if I can observer the other actions and maybe check those conditions in my test method. Thanks for your ideas. – Gagandeep Singh Mar 21 '23 at 20:28

1 Answers1

0

In your test method or test initializer you'll want to perform these setups


_mockAuthManager.Setup(am => am.AuthorizeTransaction(It.IsAny<T>()))
                        .Throws(new Exception()); // Can specify exception as well.

_mockAuthManager.SetUp(am => am.CancelTransaction(It.IsAny<T>()))
                        .Returns(It.IsAny<T>())

Then during your assertions


_mockAuthManager.Verify(am => am.CancelTransaction(It.IsAny<T>()), Times.Once);

Michael
  • 1
  • 3
  • Hello Michael, will _mockAuthManager.Setup(...) test my original implementation of the AuthorizeTransaction() method in AuthManager class? – Gagandeep Singh Mar 21 '23 at 11:53
  • I am thinking that .Setup(...) will not allow me to test the original method, it mocks the method and I am testing a mock. Is that right? If so, I don't want to test a mock implementation of my class. I want to test the actual implementation of my methods. – Gagandeep Singh Mar 21 '23 at 12:23
  • If that is the case, then you are better off just using the actual interface rather than a mock. I found [this answer](https://stackoverflow.com/a/9136721/15177106) to be insightful – Michael Mar 21 '23 at 13:35
  • Michael thanks for that link. Not sure what I am missing. I am getting an error. I updated my post above. Can you please take a look? – Gagandeep Singh Mar 21 '23 at 19:40