NSubstitute: Assert does not contain definition for Throws - c#

I am using the testing framework that comes with Visual Studio, along with NSubstitute to unit test a method that takes a system ID, and throws an exception if the system can't be found in the database...
public VRTSystem GetSystem(int systemID)
{
VRTSystem system = VrtSystemsRepository.GetVRTSystemByID(systemID);
if (system == null)
{
throw new Exception("System not found");
}
return system;
}
(In case this seems odd, there is a specific business case for this method that requires it to throw an exception, as returning a null system is not acceptable for its usage)
I want to write a test to check that an exception is thrown if the system doesn't exist. I currently have the following...
[TestMethod]
public void LicensingApplicationServiceBusinessLogic_GetSystem_SystemDoesntExist()
{
var bll = new LicensingApplicationServiceBusinessLogic();
try
{
VRTSystem systemReturned = bll.GetSystem(613);
Assert.Fail("Should have thrown an exception, but didn't.);
}
catch () { }
}
By not mocking the repository, the system returned by VrtSystemsRepository.GetVRTSystemByID() will be null, and the exception thrown. Whilst this works, it looks wrong to me. I wouldn't have expected to need a try/catch block in a test.
The NSubstitute docs have an example that implies I should be able to test this as follows...
[TestMethod]
public void GetSystem_SystemDoesntExist()
{
var bll = new LicensingApplicationServiceBusinessLogic();
Assert.Throws<Exception>(() => bll.GetSystem(613));
}
However, if I try this in my test code, I get Throws highlighted in red, with the error message "Assert does not contain definition for Throws"
Now, I'm not actually sure that the sample on that page covers my scenario, as the test code specifies that the method under test throws an exception, which I don't really understand, as I thought the idea of testing was to leave the method under test alone, and test what happens under various scenarios. However, even without that, I don't understand why the Assert.Throws method doesn't exist.
Anyone any ideas?
Edit: DavidG pointed out that Assert.Throws is probably part of NUnit, not the MS framework, which would explain why it's not recognised. If so, is the way I'm currently testing the right way to do it?

As mentioned by DavidG The referenced documentation is using NUnit for assertions.
If not using that framework you can use the ExpectedExceptionAttribute Class
[TestMethod]
[ExpectedException(typeof(<<Your expected exception here>>))]
public void GetSystem_SystemDoesntExist() {
var bll = new LicensingApplicationServiceBusinessLogic();
bll.GetSystem(613);
}
which would fail if the expected exception is not thrown.

Related

How could I allow Assert in Unit Test with [ExpectedException(typeof(ArgumentException))]?

I found, that simple Unit test
[TestMethod()]
[ExpectedException(typeof(ArgumentException))]
public void UT_UU()
{
}
gives fault with
Message: Test method did not throw expected exception
System.ArgumentException.
I successfully use [ExpetedException] to test error message output, however, any checking with Assert of side variables in the Unit Test gives it faulted.
Could I somehow decorate my test to avoid it? Or it is "political error"?
with [ExpectedException(typeof(ArgumentException))] your unit test will pass only when the method under test generates an exception of similar type you specified. In your case ArgumentException else it will fail with the message you have posted.
So essentially, you will have to fail your test method with that injection by means of injecting that exception. Currently your test method doesn't throw the expected exception (it actually doesn't perform anything)
For example below test method would pass
[TestMethod()]
[ExpectedException(typeof(ArgumentException))]
public void UT_UU()
{
throw new ArgumentException();
}
Using Assert statements in the body of the test that is decorated with ExpectedException doesn't really fit the pattern well if your test is isolated enough to only be testing one thing. If you follow the "Arrange, Act, Assert" pattern, then Assert is in this case handled by the ExpectedExceptionAttribute itself and the last line of code in the body of the test itself would be the "Act" because it should cause the exception to occur. If you need to know something more specific about the thrown exception to ensure that the system is meeting behavioral expectations, then I would use a try/catch within the test itself to be able to provide more granular inspection:
[TestMethod]
public void UT_UU()
{
// Arrange
var subject = new Foo();
try
{
// Act
subject.Bar();
}
catch(ArgumentException ae)
{
Assert.AreEqual("my message", ae.Message);
return;
}
catch(Exception e)
{
Assert.Fail("Thrown exception was of wrong type"); // would provide more detail here
}
Assert.Fail("exception should have been thrown");
}
Obviously just using ExpectedException is nice because it lets you right a very clean test without extra noise. Alternatively, if you were going to re-use this type of test you could write a derivative of ExpectedException that lets you specify other characteristics (like Message) to check instead of just the type.

Moq False Positives : MoqException is being caught by program try/catch logic

I'm writing unit tests for some legacy code and have come across a situation where I'm getting false positives for my unit tests. A simplified example is below.
If I forget to set up an implementation for DoSomething, I would want the test below to fail with a MockException. However, the exception is actually caught by the try/catch in the business logic, and so the test appears to pass. VerifyAll likewise does not cause a failure as the method has been 'called'.
I found a request for change related to this issue, but there doesn't seem to be a response to it.
Any ideas on how I can ensure this test works?
public class SUT
{
public ISystem iSystem { get; set; } // complicated web service
public void Foo()
{
try
{
iSystem .DoSomething();
}
catch (Exception ex)
{
//Report error
}
}
}
[TestClass]
public class Test
{
[TestMethod]
public void TestDoSomething()
{
var mr = new MockRepository(MockBehavior.Strict);
var iSystem = mr.Create<ISystem>();
var foo = new Foo { Interface = interface.Object };
foo.DoSomething();
mr.VerifyAll();
}
}
Your unit tests should isolate the tested class, SUT is behaving correctly by logging (and swallowing) the error - if you wanted to test the throw, that belongs in an iSystem test. You could have the test still fail by detecting the unexpected error logging call.
I believe the problem here is not really related to moq, or to testing, but more of a design / exception handling practice.
I would imagine that the constructor of Foo is not the proper place to handle all unexpected errors.
You probably want to have unexpected exceptions such as OutOfMemoryException, StackOverflowException and other unexpected exception to bubble up to a centralized place where all fatal errors will be handled.
Typically, that would be:
For WPF : the AppDomain.UnhandledException event (https://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx)
For CommandLine applications: UnhandledExceptionEventHandler (https://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx)
For ASP.Net, the Application_Error method in global.asax (https://msdn.microsoft.com/en-us/library/24395wz3(v=vs.140).aspx)
Bottom line is. In order to solve your case, first, write a brand new test where you set-up your DoSomething() method to throw an exception
Use
mr.Setup(o => o.DoSomething().Throws<MyUnexpectedException>();
Then, assert that instantiating Foo does not swallow MyUnexpectedException and is actually thrown.
By doing so, you will be forced to change your catch statement and use more specific types (it is a very bad practice to use Exception in a catch block)
Then, by changing your architecture, MockException, which inherits from Exception will not be handled by your catch block.

Ignoring exceptions handled by other assembly

I have an application for smoke testing several key services. I want these tests to be easily written and self discovering. To this end, I have created an attribute for each method in the style of [TestMethod] from MSTest. I have also created a object that will find all these methods and execute them within a try-catch. If the method throws an exception I report as a failure, otherwise as a success.
This is all very unit test familiar and that is the intention. So a test would look like...
[MyTestAttribute]
public void TestingTimesAhead()
{
var d = DateTime.MaxValue.AddDays(1);
}
The magic happens in the test object, this has an Action property and a Run method...
public Action TestAction { get; private set; }
public override ITestResult RunTest()
{
try
{
this.TestAction.Invoke();
return new BaseTestResult() { Result = TestResultStatus.Success };
}
catch(Exception ex)
{
return new BaseTestResult() { Result = TestResultStatus.Failure, FailureException = ex};
}
}
When ran in isolation the above test, being wrapped as the Action, will cause an exception and the test fails. Perfect.
However, when I wrap the attributes and test running object up into a dll and reference from a new project, VS Debugger breaks for the exception.
I am presented with an option in that dialog to toggle 'break when this exception type is user-unhandled'.
I can suppress exceptions on a type by type basis, but that isn't going to work for reuse. Also, if I run the release build from the BIN output, the expected behaviour is there - it's just a really awkward development experience.
Is it possible to manage this exception setting from my code instead? Or if anyone can suggest a way around the problem, I'm open to ideas.

How can I verify an exception was thrown with a certain parameter?

Suppose I have the following exception and method:
public MyException(string type)
{
/* Does soemthing with the parameter */
}
public void DoSomething()
{
// ...
if (/* some rule */)
throw new MyException("A");
else
{
throw new MyException("B");
}
}
I want to test my method, how can I verify using Visual Studio Unit Testing Framework that MyException with a specific parameter was thrown? I'd usually go with [ExpectedException(typeof(MyException)] but I wouldn't know which of these exceptions.
I'd usually go with [ExpectedException(typeof(MyException)]
I suggest you don't do that. You haven't told us which unit test framework you're using, but these days most provide something like:
Assert.Throws<MyException>(() => testSubject.DoSomething());
Aside from anything else, that will make sure the exception is only thrown where you expect it to be - not elsewhere.
Next, depending on your framework, you may find that Assert.Throws returns the exception thrown, so you can then validate things in that:
var exception = Assert.Throws<MyException>(...);
Assert.AreEqual("A", exception.Message);
Note that testing the exact message is generally pretty brittle - but if it's testing something else about the exception (e.g. ArgumentException.ParamName) that's more clear-cut.

Unit test throws exception but cannot see the message

Hi all I'm making a Chess AI as hobby project with Test Driven Development. But for some reason the only message my tests give is "test has thrown an exception: ...". And therefore omitting the only thing that matters. Instead of directly reading the error I now have to right-click and view test result details. I have tried adding and removing columns, but I cannot get the whole message to be shown directly.
Can VS2010 be setup so the exception message gets shown directly for each unit test?
edit: I am using standaard VS unit tests:
[TestClass]
public class MiniMaxTest
{
[TestMethod]
public void TestConstructor()
{
throw new Exception("Must I click view details to see this?");
}
}
Why these questions? You guys can reproduce these things. Debug or Run tests give the same messages:
No, I don't believe you can configure VS to show it differently. The IDE shows the first line of the exception message, and there's a newline character in the full message text, so you'll need to click through to the details to view the whole thing.
What you can do however, is abuse the MSTest framework to show your own messages.
MS Test Assertions are all implemented by throwing exceptions. All the MS Test Assert functions throw exceptions which are derived from UnitTestAssertException. Visual studio has special handling for these kinds of exceptions.
For example: If you write this test:
[TestMethod]
public void AllAboard()
{
throw new AssertFailedException("Failboat");
}
AssertFailedException is the standard base class for most other assertion failures.
You'll note that VS2010 does not print the generic "test threw an exception" message, instead it just prints "Failboat".
Now what you can do is surround your tests in things that convert normal exceptions into AssertFailedException and then you can print whatever messages you like.
[TestMethod]
public void TestStuff()
{
try
{
string o = null; // pretend this came from some real code
var x = o.Split(new[] { ',' }); // this will throw NullRefException
}
catch (Exception e)
{
throw new AssertFailedException(e.Message, e);
}
}
Of course, I wouldn't recommend actually doing this... it's verbose, and more importantly, you lose the call stack... but hey, now you've got one more tool in your toolbelt

Categories

Resources