Verify mocks in Assert.Multiple - c#

Is it possible to verify a method call in an Assert.Multiple block alongside other calls to Assert?
My current solution does not call the assert on SomeProperty, when the method call to MyMethod does not verify.
And the only way to get close to what I want would be to move the call to myInterfaceMock.Verify to the end, but that does no longer work when there are multiple method calls to verify.
var mInterfaceMock = new Mock<IMyInterface>()
.Setup(x => x.MyMethod())
.Verifiable();
var systemUnderTest = new MyClass(myInterfaceMock.Object);
systemUnderTest.MethodToTest();
Assert.Multiple(() => {
myInterfaceMock.Verify();
Assert.That(systemUnderTest.SomeProperty, Is.True);
});

The verify will throw its own exception that the assertion block wont know how to handle. That is why when the verify fails nothing gets invoked after it.
The notes in documentation also states
The test will be terminated immediately if any exception is thrown that is not handled. An unexpected exception is often an indication that the test itself is in error, so it must be terminated. If the exception occurs after one or more assertion failures have been recorded, those failures will be reported along with the terminating exception itself.
Reference Multiple Asserts
Consider the following approach
//...
Assert.Multiple(() => {
Assert.That(() => myInterfaceMock.Verify(), Throws.Nothing);
Assert.That(systemUnderTest.SomeProperty, Is.True);
});
If the verify throws an exception then it will be handled by its own assertion.

If your MethodToTest() does not return anything they I'd recommend just verifying if the method run, as you're trying to do with the assert, but I'd recommend doing something like this:
mInterfaceMock.Verify(x => x.MethodToTest(), Times.Once);
just specifying the times it has had to run, without it inside of an assertion

Related

How can I stop IConnectableObservable.Wait() from swallowing unhandled exceptions?

I have a console application using Rx.NET.
I need to block until an IConnectableObservable has completed, for which I am using IConnectableObservable.Wait().
When an unhandled exception is thrown, it is swallowed and the application hangs. I want the application to crash, and the stack track to be printed to the console.
I do not want to add an OnError handler to my IConnectableObserver because this loses the original stack trace.
I have tried using the .Wait() method on the unpublished observable, but this re-subscribes which causes undesirable behaviour.
I have tried using .GetAwaiter().GetResult() instead, but this has the same problem.
var connectable = myObservable.Publish();
connectable.Subscribe(myObserver1);
connectable.Subscribe(myObserver2);
connectable.Connect();
connectcable.Wait();
How can I wait for an IConnectableObservable to complete while retaining typical unhandled exception behaviour?
There's some misdirection in the chain of events here.
The error isn't being swallowed - far from it, it's being re-thrown.
The usual suspects are some weird concurrency and scheduling issues, but nobody suspects the Subscribe method.
When you call Subscribe with something other than your own IObserver<T>, you're creating an AnonymousObserver with these default actions.
new AnonymousObserver<T>(Ignore, Throw, Nop)
which is effectively
new AnonymousObserver<T>(_ => {}, exn => throw exn, () => {})
The default error handler will throw the error on whatever context you're observing on. Yikes. Sometimes it might be the AppDomain timer, or on a pooled thread, and since it can't be handled, your application goes down.
So if we change the sample to provide in a dummy handler,
var myObservable = Observable.Interval(TimeSpan.FromMilliseconds(100)).Take(4).Concat(Observable.Throw(new Exception(), 1L));
var connectable = myObservable.Publish();
connectable.Subscribe(Console.WriteLine, exn => Console.WriteLine("Handled"));
connectable.Subscribe(Console.WriteLine, exn => Console.WriteLine("Handled"));
connectable.Connect();
try
{
connectable.Wait();
}
catch (Exception)
{
Console.WriteLine("An error, but I'm safe");
}
You can handle the error in the Wait like you'd expect to.

How to Cleanly Exit Topshelf

Based off the sample at this question which deals with passing custom parameters to Topshelf, I now want to be able to cleanly exit out of the Topshelf HostFactory.
I have the following code, and it does work, but when it "returns", the console displays an ugly error stating Topshelf.HostFactory Error: 0 : An exception occurred creating the host... The service was not properly configured... ServiceBuilderFactory must not be null
What should I uses instead of return to simply tell Topshelf to exit and not do anything?
string foo = null;
HostFactory.Run(x =>
{
x.AddCommandLineDefinition("foo", f => { foo = f; });
x.ApplyCommandLine();
if (!string.IsNullOrEmpty(foo))
{
Console.WriteLine("A value for Foo was received... exiting.");
return;
}
x.Service<MyService>(s =>
{
s.ConstructUsing(() => new MyService());
s.WhenStarted(z => z.Start());
s.WhenStopped(z => z.Stop());
});
x.StartAutomatically();
});
In this case, you should not be calling .ApplyCommandLine() in your code, that's automatically handled by Topshelf. And it's important to recognize that you're configuring the host at this point, and should not be throwing an exception.
The best place for your command-line value check is in the ConstructUsing() method, where you can verify the command-line arguments are present. If your conditions are not satisfied, throw an exception and the service will fail to start.
If you do it anywhere else, the command-line options for install/uninstall/etc. will not work without that command-line parameter specified.

Why My Assert Fails? (Exception thrown)

I'm using testing in my code, and by my understanding, all a test requires to run in a method is this:
private ClassName(Argument)
{
return;
}
So what the test is actually checking is if the "Argument" is the correct output at the end of the method/test.
However in my case the argument passed in has nothing to do with the output. Therefore I am uncertain of how to test it.
NOTE: The code itself is sound, it outputs the correct variables. Also I actually wrote the test after the code (Big booboo, I know. I want to get into the habit of always testing.)
EDIT: I believe the issue is to do with the Test being exited via the LoginView.Close and LoginView.Menu.SetMenuView. (The function ends on this line, and the test cannot complete?)
The Location of the return; also affects the rest of the code, so it needs to be at the end of the code. If I move it up, the rest of the code becomes unreachable, and the program breaks.
I have looked for ways to try and bypass the exceptions, and all I have come up with is to test that the exception is actually being thrown correctly. Is there a way to bypass the exception in the test?
Here is the test:
public void Compare_LoginTest()
{
User_LoginView LoginView = new User_LoginView();
User_Controller.screenName = "ben";
User_Controller.screenPwd = "password";
User_Controller.Compare_Login(LoginView);
int actual = User_Controller.screenAccess;
int expected = 1;
Assert.AreEqual(expected, actual);
}
Here is the method being tested:
public static void Compare_Login(User_LoginView LoginView)
{
// Creates a new oject of User_Model and populates it from the User_Controller.
User_Model AccessModel = new User_Model();
AccessModel.Name = screenName;
AccessModel.Pwd = screenPwd;
// Runs the Login Comparsion in the Database_Facade, and passes in the Model.
Database_Facade Database = new Database_Facade();
Database.GetLoginAccess(AccessModel);
screenAccess = AccessModel.AccessLevel;
Menu_View.accessLevelSet = AccessModel.AccessLevel;
// Compares the returned AccessLevel.
// if it is corect; closes the Login and runs the SetMenuView method,
// if it is incorrect; shows an error.
if (AccessModel.AccessLevel > 0)
{
Console.WriteLine("Access Level " + AccessModel.AccessLevel);
// Exception Thrown in testing.
LoginView.Close();
LoginView.Menu.SetMenuView();
}
else
{
ErrorCodes_Controller LoginError = new ErrorCodes_Controller();
LoginError.WrongLoginError();
}
return;
}
I don't understand what you're asking... The test will pass if the static UserController.screenAccess variable is 1 - and it looks like the Compare_Login method always sets it to 1.
This all looks fine, so if your test is failing, then there's something preventing the code from reaching that point.
For most unit test frameworks (I'm guessing you're just using the built in microsoft one?), exceptions are how unit test methods pass or fail - The Assert.Xyz methods throw an exception if the assertion isn't right, otherwise they don't. Any other exceptions that your code may throw also count as a fail.
The test framework catches any exceptions and flags the test as passed if there aren't any
I would guess that something in the Check_Login function or earlier in the Compare_Login function is throwing an exception. This is the only thing I can see that would cause your unit test to fail. I'm surprised however that you haven't noticed such an exception (try clicking on the failing unit test and seeing what details you can see about the failure)

MsTest TestCleanup method not called when an unhandled exception is thrown

I have a test which uses an external assembly to access UI features in the application we're testing. This assembly throws an exception of its own custom type if the UI is not in the appropriate state.
I've set up a TestCleanup method that kills the application's process (while a TestInitialize starts it) so that after a test run has been completed, the UI is restarted with a clean state.
This work well under regular conditions, however, whenever an exception from the referenced assembly is thrown, it never gets to the cleanup method and jumps straight ahead to the next test. This doesn't happen with exceptions thrown from the test itself, like AssertFailedException. I even tried throwing a basic Exception from the test, and it got to the cleanup method.
If an exception is uncaught in TestInitialize, TestCleanup won't be called.
http://web.archive.org/web/20140310065725/http://connect.microsoft.com/VisualStudio/feedback/details/694337/testcleanup-method-does-not-run-when-it-should
When MSTest fails in TestInitialize, why doesn't TestCleanup get executed?
Under what circumstances are [ClassCleanup] and [TestCleanup] not run
This unfortunately diverges from the way C# handles exceptions in constructors : when this happens, the finalizer is called.
But you can directly call CleanUp method from the catch block
[TestCleanup]
public void Clenup()
{
..............
}
[TestMethod]
public void Test1()
{
try
{...................}
catch (Exception e)
{
Cleanup();
throw new Exception();
}
}
That was fixed in MsTest v2.
https://github.com/Microsoft/testfx/issues/250
Extract from the above link:
This was a conscious compat break to give unit test writers a choice to cleanup partially
initialized methods.

I want to assert that an exception was thrown within a certain class

I am building a TestProject for my client/server setup. I want to verify that a test fails within a certain block of execution (there is no client to send to so the server's Send() method will throw an exception). Since I do not want to have the tests boot up a client and server and have them communicate (which I have had problems doing on a single machine.)
If the code reaches this line, that means that the program's execution flow could only fail within the responsibilities of another test. Is there an easier way to do this other than doing a substring check on the thrown exception's stacktrace? I feel like this method is not very expandable and would require constant attention if class names change.
Is there a way that doesn't even involve manually checking the exception's stacktrace?
If you are using NUnit
Without using DataAnnotations
[Test]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
Assert.That(()=>yourClass.Method(),
.Throws.Exception
.TypeOf<TypeOfYourException>
.With.Property("Message")
.EqualTo("the message you are expecting goes here")
);
}
Using DataAnnotations
[Test]
[ExpectedException(typeof(ExceptionType), ExpectedMessage="your message goes here!")]
public void Test_XXXXXXX
{
var yourClass = new YourClass();
// Call your method in a way that it will fail
yourClass.YourMethod();
}
Is there anything unique about the exception in the class, other than that it's specific to that class?
If it's identifiable by the message you can test it as the other answer has shown, or like this if you're not using NUnit:
try {
myMethod();
Assert.Fail("Expected exception to be thrown.");
} catch (MyException ex) {
Assert.Equals("My Exception Message", ex.Message, "Exception message was formatted incorrectly.");
} catch (Exception) {
Assert.Fail("An exception was thrown, but of the wrong type.");
}
When you are unit-testing some class, there is two sources of exception:
Class which you are testing can throw an exception
Dependency of a class can throw an exception
In second case you usually either handle exception, or wrap it in more high-level exception and throw it to caller. So, how to test all these cases?
System under test throws exception
E.g. throwing exception in case of wrong argument passed to method (NUnit sample):
StockService service = new StockService();
Assert.Throws<ArgumentNullException>(() => service.Connect(null));
You don't need to check stack trace, because it's a class under test who supposed to throw exception.
Dependency throws exception and we handle it
When your class has dependencies, you should mock dependencies in order to test your class in isolation. So, it's very easy to setup mocks to throw exceptions when your class interacts with them. Consider case when service should run on default settings if configuration file not found (Moq sample):
var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();
StockService service = new StockService(configMock.Object);
service.Connect("google");
configMock.VerifyAll();
Assert.That(service.Port, Is.EqualTo(80));
This test will fail if you will not try to load config, or if you will not handle FileNotFoundException.
Exception stacktrace does not matters here - we don't care whether our direct dependency thrown exception, or it was some other class inside dependency. Actually we don't know if that class exists - we are interacting only with direct dependency. And we should care only about fact that dependency can throw exception, which we can handle.
Dependency throws exception and we wrap it
And last case - wrapping exception in something more high-level. Consider previous sample, but config is really important and you can't start without configuration file. In this case you wrap FileNotFoundException into something more business-specific, which makes sense at higher levels of your application. E.g. StockServiceInitializationException:
var configMock = new Mock<IStockServiceConfig>();
configMock.Setup(c => c.Load()).Throws<FileNotFoundException>();
StockService service = new StockService(configMock.Object);
Assert.Throws<StockServiceInitializationException>(_ => service.Connect("bing"));
configMock.VerifyAll();
As you can see, we also don't care about stacktrace of exception, which throws our dependency. It also could be some wrapper of more low level exception. Expected behavior of service - throw high-level initialization exception if config not found. We are verifying that behavior here.

Categories