/*
* The contents of this file are subject to the OpenMRS Public License
* Version 2.0 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
* http://license.openmrs.org
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and
* limitations under the License.
*
* Copyright (C) OpenHMIS. All Rights Reserved.
*/
package org.openmrs.module.openhmis.cashier.api;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.powermock.api.mockito.PowerMockito.mock;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.openmrs.api.APIException;
import org.openmrs.api.AdministrationService;
import org.openmrs.api.context.Context;
import org.openmrs.module.openhmis.cashier.ModuleSettings;
import org.openmrs.module.openhmis.cashier.api.test.AnotherTestReceiptNumberGenerator;
import org.openmrs.module.openhmis.cashier.api.test.InvalidReceiptNumberGenerator;
import org.openmrs.module.openhmis.cashier.api.test.TestReceiptNumberGenerator;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
@RunWith(PowerMockRunner.class)
@PrepareForTest(Context.class)
public class ReceiptNumberGeneratorFactoryTest {
protected static final int TEST_GENERATOR_CLASSES = 2;
protected AdministrationService administrationService;
@Before
public void before() {
administrationService = mock(AdministrationService.class);
mockStatic(Context.class);
when(Context.getAdministrationService())
.thenReturn(administrationService);
}
@After
public void after() {
ReceiptNumberGeneratorFactory.reset();
}
/**
* @verifies Return the currently defined receipt number generator
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test
public void getGenerator_shouldReturnTheCurrentlyDefinedReceiptNumberGenerator() throws Exception {
// Configure system generator
when(administrationService.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR))
.thenReturn(TestReceiptNumberGenerator.class.getName());
// Get the generator from the factory
IReceiptNumberGenerator generator = ReceiptNumberGeneratorFactory.getGenerator();
// Ensure that the correct generator was returned
Assert.assertNotNull(generator);
Assert.assertEquals(TestReceiptNumberGenerator.class, generator.getClass());
// Get the generator again
generator = ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNotNull(generator);
Assert.assertEquals(TestReceiptNumberGenerator.class, generator.getClass());
// Ensure that the admin service was only called once
verify(administrationService, times(1))
.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR);
}
/**
* @verifies Load the generator if it has not been loaded.
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test
public void getGenerator_shouldLoadTheGeneratorIfItHasNotBeenLoaded() throws Exception {
when(administrationService.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR))
.thenReturn(TestReceiptNumberGenerator.class.getName());
TestReceiptNumberGenerator generator = (TestReceiptNumberGenerator)ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNotNull(generator);
Assert.assertEquals(true, generator.isLoaded());
Assert.assertEquals(1, generator.getLoadedCount());
}
/**
* @verifies not load the generator if it has been loaded.
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test
public void getGenerator_shouldNotLoadTheGeneratorIfItHasBeenLoaded() throws Exception {
TestReceiptNumberGenerator generator = new TestReceiptNumberGenerator();
generator.load();
Assert.assertEquals(true, generator.isLoaded());
Assert.assertEquals(1, generator.getLoadedCount());
ReceiptNumberGeneratorFactory.setGenerator(generator);
generator = (TestReceiptNumberGenerator)ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertEquals(true, generator.isLoaded());
Assert.assertEquals(1, generator.getLoadedCount());
}
/**
* @verifies Return null if no generator has been defined
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test
public void getGenerator_shouldReturnNullIfNoGeneratorHasBeenDefined() throws Exception {
when(administrationService.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR))
.thenReturn(null);
IReceiptNumberGenerator generator = ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNull(generator);
}
/**
* @verifies Throw APIException if generator class cannot be found
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test(expected = APIException.class)
public void getGenerator_shouldThrowAPIExceptionIfGeneratorClassCannotBeFound() throws Exception {
when(administrationService.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR))
.thenReturn("org.openmrs.module.openhmis.cashier.NotAValidClass");
ReceiptNumberGeneratorFactory.getGenerator();
}
/**
* @verifies Throw APIException if generator class cannot be instantiated
* @see ReceiptNumberGeneratorFactory#getGenerator()
*/
@Test(expected = APIException.class)
public void getGenerator_shouldThrowAPIExceptionIfGeneratorClassCannotBeInstantiated() throws Exception {
when(administrationService.getGlobalProperty(ModuleSettings.SYSTEM_RECEIPT_NUMBER_GENERATOR))
.thenReturn(InvalidReceiptNumberGenerator.class.getName());
ReceiptNumberGeneratorFactory.getGenerator();
}
/**
* @verifies Locate all classes that implement IReceiptNumberGenerator
* @see ReceiptNumberGeneratorFactory#locateGenerators()
*/
@Test
public void locateGenerators_shouldLocateAllClassesThatImplementIReceiptNumberGenerator() throws Exception {
IReceiptNumberGenerator[] generators = ReceiptNumberGeneratorFactory.locateGenerators();
Assert.assertNotNull(generators);
Assert.assertTrue(generators.length >= 2);
boolean foundTest1 = false, foundTest2 = false;
for (IReceiptNumberGenerator generator : generators) {
if (generator.getClass().equals(TestReceiptNumberGenerator.class)) {
foundTest1 = true;
} else if (generator.getClass().equals(AnotherTestReceiptNumberGenerator.class)) {
foundTest2 = true;
}
if (foundTest1 && foundTest2) {
break;
}
}
Assert.assertTrue("Both of the two test receipt number generators were not located.", foundTest1 && foundTest2);
}
/**
* @verifies Not throw an exception if the class instantiation fails
* @see ReceiptNumberGeneratorFactory#locateGenerators()
*/
@Test
public void locateGenerators_shouldNotThrowAnExceptionIfTheClassInstantiationFails() throws Exception {
IReceiptNumberGenerator[] generators = ReceiptNumberGeneratorFactory.locateGenerators();
Assert.assertNotNull(generators);
Assert.assertTrue(generators.length >= 2);
boolean foundInvalidGenerator = false;
for (IReceiptNumberGenerator generator : generators) {
if (generator.getClass().equals(InvalidReceiptNumberGenerator.class)) {
foundInvalidGenerator = true;
break;
}
}
Assert.assertFalse("The invalid generator was unexpectedly located.", foundInvalidGenerator);
}
/**
* @verifies Use the existing instance for the currently defined generator
* @see ReceiptNumberGeneratorFactory#locateGenerators()
*/
@Test
public void locateGenerators_shouldUseTheExistingInstanceForTheCurrentlyDefinedGenerator() throws Exception {
IReceiptNumberGenerator generator = new TestReceiptNumberGenerator();
ReceiptNumberGeneratorFactory.setGenerator(generator);
IReceiptNumberGenerator[] generators = ReceiptNumberGeneratorFactory.locateGenerators();
Assert.assertNotNull(generators);
Assert.assertTrue(generators.length >= 2);
boolean foundGeneratorInstance = false;
for (IReceiptNumberGenerator gen : generators) {
if (gen.getClass().equals(TestReceiptNumberGenerator.class)) {
foundGeneratorInstance = (gen == generator);
break;
}
}
Assert.assertTrue("A new generator instance was created when the existing should have been reused.",
foundGeneratorInstance);
}
/**
* @verifies Set the receipt number generator for the system
* @see ReceiptNumberGeneratorFactory#setGenerator(IReceiptNumberGenerator)
*/
@Test
public void setGenerator_shouldSetTheReceiptNumberGeneratorForTheSystem() throws Exception {
// Set the generator
IReceiptNumberGenerator generator = new TestReceiptNumberGenerator();
ReceiptNumberGeneratorFactory.setGenerator(generator);
generator = ReceiptNumberGeneratorFactory.getGenerator();
// Ensure that the correct generator was returned
Assert.assertNotNull(generator);
Assert.assertEquals(TestReceiptNumberGenerator.class, generator.getClass());
IReceiptNumberGenerator generator2 = new AnotherTestReceiptNumberGenerator();
ReceiptNumberGeneratorFactory.setGenerator(generator2);
generator = ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNotNull(generator);
Assert.assertEquals(AnotherTestReceiptNumberGenerator.class, generator.getClass());
}
/**
* @verifies Remove the current generator if set to null
* @see ReceiptNumberGeneratorFactory#setGenerator(IReceiptNumberGenerator)
*/
@Test
public void setGenerator_shouldRemoveTheCurrentGeneratorIfSetToNull() throws Exception {
// Set the generator
IReceiptNumberGenerator generator = new TestReceiptNumberGenerator();
ReceiptNumberGeneratorFactory.setGenerator(generator);
generator = ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNotNull(generator);
ReceiptNumberGeneratorFactory.setGenerator(null);
generator = ReceiptNumberGeneratorFactory.getGenerator();
Assert.assertNull(generator);
}
}