TestsTested | ✓ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Dec 2016 |
Maintained by Odina Software.
MockWebServer is a very simple web server that is solely designed to work with XCTest framework. MockWebServer mocks a web server's behavior. User can specify server's response headers and body by matching request pattern. The idea is that it can work simiarly with MockWebServer by Square for Android so that a unit test or UI test can perform test case based on server's response. Since user can specify the server's response in a test case, user can determine how a test case should behave.
MockWebServer is compatible with objective-c and swift, and also it can work with Cocoapods or Carthage. To use MockWebServer in Carthage, you can simple add this line to Carfile
.
github "odinasoftware/MockWebServer"
MockWebServer is impemented by objective-c only so that it can work with objective-c or any version of swift.
MockWebServer requires local connection to the server. Therefore user will need to connect to localhost
and the port number MockWebServer is listening.
For instance, if the server start with mockWebServer.start(9000)
, user may connect to MockWebServer as shown below:
let url = NSURL(string: "http://127.0.0.1:9000/test")
...
let task = URLSession.shared.dataTask(with: url! as URL) {
(data, response, error) in
...
}
If user wants to run app transparently in a unit test, user will need to confiure app's environment to change to connect to localhost
when it is running from a test case. For instance, in setUp
user may set up environment like this:
let app = XCUIApplication()
app.launchEnvironment["LOCAL_SERVER"] = "YES"
app.launch()
Now in you application is launched, you can check to see if it is launced from UI test case like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
if ([[NSProcessInfo processInfo].environment objectForKey:@"LOCAL_SERVER"] != nil) {
// Your environment detects UI test, use local server instead.
}
return YES;
}
To run the example project, clone the repo, and run pod install
from the Example directory first.
Initialize MockWebServer
in setUp
and run start
with port number for the server.
- (void)setUp {
[super setUp];
mockWebServer = [[MockWebServer alloc] init];
[mockWebServer start:9000];
}
When a test case is completed, you will need to stop the server by running stopServer
. You can run stopServer
when a test is tearing down.
- (void)tearDown {
[super tearDown];
[mockWebServer stopServer];
}
A dispatch will hold a request pattern to mock and response headers and response body to mock.
Dispatch *dispatch = [[Dispatch alloc] init];
[dispatch requestContainString:@"test"];
[dispatch setResponseCode:200];
[dispatch responseString:@"test"];
[dispatch responseHeaders:@{@"Accept-encoding": @"*.*"}];
This will match any request contains "test" and will generate response code 200 and the response headers indicated. And the response body will be "test". After a dispatch is created, you will need to add the dispatch to a dispatchMap and set it to the mock server.
[dispatchMap addDispatch:dispatch];
[mockWebServer setDispatch:dispatchMap];
You may use NSURLSessionDataTask
to run a normal url request.
NSString *dataUrl = @"http://127.0.0.1:9000/test";
NSURL *url = [NSURL URLWithString:dataUrl];
NSURLSessionDataTask *test = [[NSURLSession sharedSession]
dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// 4: Handle response here
NSLog(@"data=%@", [NSString stringWithUTF8String:[data bytes]]);
XCTAssert([[NSString stringWithUTF8String:[data bytes]] compare:@"test"]==0, @"Body doesn't match.");
[testWait wakeup];
}];
Since the task is asynchronous, the test must wait until the asynchrnous taks is completed. You may want to use helper function to do that. First you will need to create TestConditionWait
and you will need to wait after the url task is resumed.
TestConditionWait *testWait = [TestConditionWait instance];
...
[test resume];
[testWait waitFor:1];
testWait
will wait until [testWait wakeup]
is called. User can also specifiy how many thread it has to wait.
User will need to start MockWebServer in setup()
with the port number for the server.
override func setUp() {
super.setUp()
...
mockWebServer.start(9000)
}
User will need to stop the server when a unit test is completed.
override func tearDown() {
super.tearDown()
...
mockWebServer.stop()
}
As it's done in objective-c example, user will need to specify a dispatch for a response.
let dispatch: Dispatch = Dispatch()
dispatch.requestContain("test1")
.setResponseCode(200)
.responseString("test")
.responseHeaders(["Accept-encoding": "*.*"])
dispatchMap.add(dispatch)
User can also have multiple dispatch to simulate mubliptle response in a test case.
let dispatch1: Dispatch = Dispatch()
dispatch1.requestContain("test2")
.setResponseCode(200)
.responseBody(for: Bundle(for: object_getClass(self)), fromFile: "response.json")
.responseHeaders(["Accept-encoding": "*.*"])
dispatchMap.add(dispatch1)
Not user created two dispates, which correspnd to two responses. User will need to add those dispatches to the dispatch map.
mockWebServer.setDispatch(dispatchMap)
let task = URLSession.shared.dataTask(with: url! as URL) {
(data, response, error) in
debugPrint("response data=", data ?? "response null")
debugPrint("response headers=", response ?? "no response header")
testCondition.wakeup()
}
task.resume()
let task2 = URLSession.shared.dataTask(with: url2! as URL) {
(data, response, error) in
debugPrint("response data=", data ?? "response null", "\n")
debugPrint("response headers=", response ?? "no response header", "\n")
testCondition.wakeup()
}
task2.resume()
testCondition.wait(for: 2)
As shown in objective-c example, user can use TestConditionWait
to wait until data thread to finish. In this case, we have two data tasks to wait.
MockWebServer is available through CocoaPods. To install it, simply add the following line to your Podfile:
pod "MockWebServer"
Jae Han, [email protected]
MockWebServer is available under the MIT license. See the LICENSE file for more info.