How to Unit Test Windows Phone 8 MVVM Async Commands? - unit-testing

I want to write some unit test for some Commands in My ViewModel Class.
I want to test the execution of an ICommand.
My ICommand.Execute() method executes an async method.
how can I write a test case for this command ?
Note: I'm using The Windows Phone Unit Test framework delivered in CTP2 of Visual Studio 2012 Update 2 http://blogs.msdn.com/b/visualstudioalm/archive/2013/01/31/windows-phone-unit-tests-in-visual-studio-2012-update-2.aspx

It's much easier to test async Task methods; that is, have your async void Execute implementation just await an async Task method, which is the one that's actually unit tested.
The built-in MSTest unit test framework does not support testing async void methods, since it's a bit involved and would raise backwards-compatibility issues. Currently, NUnit is the only unit testing framework that supports async void methods.
If you really want to test an async void method and don't want to use NUnit, you can use Stephen Toub's AsyncPump or my AsyncContext (available on NuGet) to create your own context for each unit test. In this case, your test will look something like:
[TestMethod]
public void TestMyAsyncVoidMethod()
{
ICommand myCommand = ...;
AsyncContext.Run(() =>
{
myCommand.Execute();
Assert.IsTrue(command-is-in-progress);
});
Assert.IsTrue(command-completed);
}

I'd assume you'd tag the method with the [Asynchronous] attribute and then just call await ICommand.Execute()
Check this post for a sample of asynchronous Windows Phone method testing.

You should change your test method signature to
[TestMethod]
public async Task TestMyAsyncVoidMethod()
{....
So that you can await you command execute method.

Related

To develop a testing tool

Now, I am trying to develop a testing tool, which can make unit testing. I mean I want to use JUnit in my testing tool to test other projects. But I don't know how to insert JUnit into my testing tool. Is it possible to do that and how? And is there any other open-source testing tool can be inserted into my testing tool?
To use Junit API make sure you got the jar in the classpath
To use Junit tests you need the testing class to extend SystemTestCase4
and your function to have #Test annotation above it
if you want code to run before your test so use function with #Before
and if you want after use function with #After
public class BaseTest extends SystemTestCase4 {
#Before
public void beforeEachTest() throws Exception {
}
#Test
#TestProperties(name = "test test ")
public void testTest() throws Exception {
//run your tested code
}
#After
public void afterEachTest() throws Exception {
}
as for how to test your projects it depend what tests you want to do?
For unit testing just add your own tests inside the projects
Integration, Functional or other tests need you to understand how to "Attack" it, meaning if it's UI tests for web so use tools for that (Selenium for example) if it's for checking network so use JMeter

Can't overload async/await methods with NUnit Test Adapter

I'm getting a System.Reflection.AmbiguousMatchException when at least one of the methods are async and the method names match when the NUnit tests are run using the NUnit Test Adapter 2.0.0.0 in Visual Studio. I'm able to run the tests without problem when I use the ReSharper unit test runner and when I use the NUnit GUI test runner (NUnit-2.6.4.msi). Is this a bug in the NUnit Test Adapter?
[TestFixture]
public class SimpleRepro
{
[Test]
[TestCase("I'm valid")]
[TestCase("So am I!")]
public async Task Foo(string resource)
{
Assert.IsNotNull(resource);
await Task.Delay(new TimeSpan(0, 0, 1));
}
[Test]
public async Task Foo()
{
Assert.IsNotNull(Guid.NewGuid().ToString("N"));
await Task.Delay(new TimeSpan(0, 0, 1));
}
}
I've cross posted this on the GitHub issues list.
This was confirmed as a bug by one of the library owners. According to their comment it looks like this will be addressed in a future release:
Since it only occurs in the adapter, it should be something we can fix!
This is great news of course. In the mean time you can work around this issue by not overloading async/await methods in your unit tests.

What test to write?

I know this is a basic question but due to lack of my knowledge I couldn't start writing test for my application. So here I am trying to learn and understand what to test and how to test based on my application scenario.
Class MyController {
MyService service = new MyService();
List<String> myList = service.generateSomeList(keyVal);
model.add("myList", myList);
}
Class MyService {
ThirdPatryService extService = new ThirdPatryService ();
MyDao dao = new MyDao();
public List<String> generateSomeList(Long key) {
List<String> resultList = dao.fetchMyList(key);
extService.processData(resultList); //using 3rd party service to process result. It doesn't return anything.
return formattedList(resultList);
}
private List<String> formattedList(List<String> listToProcess) {
//do some formatting
}
}
Class MyDao {
List<String> fetchMyList(key) {
//Use DB connection to run sql and return result
}
}
I want to do both unit testing and integration testing. So some of my questions are:
Do I have to do unit testing for MyDao? I don't think so since I can test query result by testing service level.
What can be the possible test cases for service level? I can think of test result from db and test formatting function. Any other test that I missed?
While testing generateSomeList() method is that OK to create dummy String list and test it against result? Like code below Am I creating list myself and testing myself. IS this proper/correct way to write test?
#Test
public void generateSomeListTest() {
//Step 1: Create dummy string list e.g. dummyList =["test1", "test2", "test3"]
//Step 2: when(mydao.fetchMyList(anyLong()).thenReturn(dummyList);
//Step 4: result=service.generateSomelist(123L);
//Step 5: assertEquals(result[i], dummyList[i]);
}
I don't think I have to test third party service but I think I have to make sure it is being called. Is this correct? If yes how can I do that with Mockito?
How to make sure thirdparty service has really done the processing of my data. Since its return type is void how can I do test it really done its job e.g like send email
Do I have to write test for controller or I can just write integration test.
I really appreciate if you could answer these question to understand the testing part for the application.
Thanks.
They're not really unit tests, but yes, you should test your DAOs. One of the main points in using DAOs is precisely that they're relatively easy to test (you store some test data in the database, then call a DAO method which executes a query, and check that the method returns what it should return), and that they make the service layer easy to test by mocking the DAOs. You should definitely not use the real DAOs when testing the services. Ue mock DAOs. That willmake the service tests much simpler, and much much faster.
Testing the results from DB is the job of the DAO test. The service test should use a mock DAO that returns hard-coded results, and checks that the service foes what it should do with these hard-coded results (formatting, in this case)
Yes, it's fine.
Usually, it's sufficient to stub the dependencies. Verifying that they have been called is often redundant. In that case, it could be a good idea since the third party service doesn't return anything. But that's a code smell. Why doesn't it return something? See the method verify() in Mockito. It's the very first point in the Mockito documentation: http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#1
The third party service is supposed to have been tested separately and thus be reliable. So you're supposed to assume that it does what its documentation says it does. The test for A which uses B is not supposed to test B. Only A. The test of B tests B.
A unit test is usually simpler to write and faster to execute. It's also easier to test corner cases with unit tests. Integration tests should be more coarse-grained.
Just a note: what your code severely lacks as is is dependency injection. That's what will make your code testable. It's very hard to test as is because the controller creates its service, which creates its DAO. Instead, the controller should be injected with the service, and the service should be injected with the DAO. That's what allows injecting a mock DAO in the service to test the service in isolation, and to inject a mock service into the controller to test the controller in isolation.

How to unit test netty handler

I implement a handler which extends SimpleChannelHandler, and overrides some methods such as channelConnected, messageReceived. However, I am wondering how to unit test it?
I searched about "netty unit test" and found one article which said considering CodecEmbedder, but I am still not sure how to begin. Do you have any example or advice on how to unit test Netty code?
Thanks a lot.
In Netty, there are different ways to test your networking stack.
Testing ChannelHandlers
You can use Netty's EmbeddedChannel to mock a netty connection for testing, an example of this would be:
#Test
public void nettyTest() {
EmbeddedChannel channel = new EmbeddedChannel(new StringDecoder(StandardCharsets.UTF_8));
channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{(byte)0xE2,(byte)0x98,(byte)0xA2}));
String myObject = channel.readInbound();
// Perform checks on your object
assertEquals("☢", myObject);
}
This test above tests for StringDecoder ability to decode unicode correct (example from this bug posted by me)
You can also test the encoder direction using EmbeddedChannel, for this you should use writeOutBound and readInbound.
More Examples:
DelimiterBasedFrameDecoderTest.java:
#Test
public void testIncompleteLinesStrippedDelimiters() {
EmbeddedChannel ch = new EmbeddedChannel(new DelimiterBasedFrameDecoder(8192, true,
Delimiters.lineDelimiter()));
ch.writeInbound(Unpooled.copiedBuffer("Test", Charset.defaultCharset()));
assertNull(ch.readInbound());
ch.writeInbound(Unpooled.copiedBuffer("Line\r\ng\r\n", Charset.defaultCharset()));
assertEquals("TestLine", releaseLater((ByteBuf) ch.readInbound()).toString(Charset.defaultCharset()));
assertEquals("g", releaseLater((ByteBuf) ch.readInbound()).toString(Charset.defaultCharset()));
assertNull(ch.readInbound());
ch.finish();
}
More examples on github.
ByteBuf
To test if you use your bytebufs, you can set a JVM parameter that checks for leaked ByteBuf, for this, you should add -Dio.netty.leakDetectionLevel=PARANOID to the startup parameters, or call the method ResourceLeakDetector.setLevel(PARANOID).

How to unit test a synchronous method calling asynchronous method?

What is the correct way to write a unit test for a synchronous method calling async methods.
Right now my unit test are passing, but when I try to open the page, it never returns.
Why isn't my unit test failing? How can I make it fail?
I replicated my problem with this simple code:
My passing test:
[TestMethod]
public void DoSomeWork_WhenWeDoSomeWork_ShouldReturnDone()
{
var service = new SyncService();
const string expected = "Done";
var actual = service.DoSomeWork();
Assert.AreEqual(expected, actual);
}
My view that never returns:
public ActionResult Index()
{
var syncService = new SyncService();
return View((object)syncService.DoSomeWork());
}
My service that never returns to view:
public class SyncService
{
public string DoSomeWork()
{
return SomeWork().GetAwaiter().GetResult();
}
private async Task<string> SomeWork()
{
var task1 = Task.Delay(1000);
var task2 = Task.Delay(1000);
await Task.WhenAll(task1, task2);
return "Done";
}
}
I don't think I can help you with this specific example, but I think a good general strategy is to write two tests. One to test if the synchronous method passes the correct data and an other to test if the asynchronous method works properly.
I mostly work in JavaScript and that general approach works for me. Also you can check the documentation of your testing frameworks, maybe it provides some methods for this.
First, don't block on async code (link to my blog). By blocking on async code, you're actually causing a deadlock. This deadlock does not happen in your unit test because unit tests run in a thread pool context, not an ASP.NET context (link to my blog).
There are good reasons for not having synchronous wrappers for asynchronous methods. So I recommend getting rid of DoSomeWork completely, leaving only SomeWork (renamed to SomeWorkAsync).
To solve your problem, you should use asynchronous controller actions.