Starting a server for testing

We will start a server instance in a separate thread, because Rust runs tests in multiple threads, and we won't create a server instance with a unique port for every test run to show how you can use a shared instance, because integration tests often need to reuse the same application instance. Create a shared flag that we will use to detect routers that have already started:

lazy_static! {
static ref STARTED: Mutex<bool> = Mutex::new(false);
}

Now, we will use this Mutex to create a function to start a server. Look at the following setup function implementation:

fn setup() {
let mut started = STARTED.lock().unwrap();
if !*started {
thread::spawn(|| {
let url = mockito::server_url();
let _signup = add_mock("POST", "/signup", ());
let _signin = add_mock("POST", "/signin", UserId { id: "user-id".into() });
let _new_comment = add_mock("POST", "/new_comment", ());
let comment = Comment {
id: None,
text: "comment".into(),
uid: "user-id".into(),
};
let _comments = add_mock("GET", "/comments", vec![comment]);
let links = LinksMap {
signup: mock_url(&url, "/signup"),
signin: mock_url(&url, "/signin"),
new_comment: mock_url(&url, "/new_comment"),
comments: mock_url(&url, "/comments"),
};
start(links);
});
thread::sleep(Duration::from_secs(5));
*started = true;
}
}

The preceding function locks a Mutex to get the value of the flag. If it equals false, we spawn a new thread with a server instance and mocks, and wait 5 seconds before we set the flag to true and release the Mutex.

In the spawned thread, we get a URL or mock server. It automatically starts that server if it wasn't started already. After this, we use the add_mock method to add all mocks to emulate other microservices.

The mockito crate requires you to have added all the mocks in the same thread in which the mock server started.

Also, we keep all crated mocks in local variables. If any of them are dropped, then that mocking handler will be lost. You can also use the std::mem::forget method to ensure that the mock will be never dropped, but it's more accurate to leave the local variable.

We will employ LinksMap using the URL of the mock server and paths, both of which are concatenated with the following function:

fn mock_url(base: &str, path: &str) -> String {
format!("{}{}", base, path)
}

Finally, we called the start function, which is actually a modified main function:

fn start(links: LinksMap) {
let sys = actix::System::new("router");
let state = State {
counter: RefCell::default(),
links,
};
server::new(move || {
App::with_state(state.clone())
// App resources attached here
}).workers(1).bind("127.0.0.1:8080").unwrap().start();
sys.run();
}

The difference between this and the main function of the router microservice of Chapter 11, Involving Concurrency with Actors and Actix Crate, is that it expects the LinksMap value to add it to State. Now, we can create methods to perform testing requests to a server that resends them to mocks.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.182.159