Mock static variable Mockito - spring

// Service
protected static Processor aProcessor = new AProcessor();
protected static Processor bProcessor = new BProcessor();
protected static Processor chain;
static {
validateProcessor.setNextProcessor(bProcessor);
chain = aProcessor;
}
public void method() {
chain.process(new Abc());
}
// AProcessor
public void process(Abc abc) {
System.out.println("AProcessor");
}
// Test
#Mock
private Processor aProcessor;
#Test
public void test() {
service.method();
verify(aProcessor, times(1)).process(any(Abc.class));
}
I'm trying to mock aProcessor and I want to check that process method called 1 time. But it couldn't mock, it's printing "AProcessor" text. Any suggestion to solve it?

Related

How to test a try...finally method only been called once in SpringBoot?

I am following this article to implement a database read/write separation feature by calling different methods. However, I got the error:
Missing method call for verify(mock) here: verify(spyDatabaseContextHolder, times(1)).set(DatabaseEnvironment.READONLY);
when doing the testing.
My test case is trying to verify DatabaseEnvironment.READONLY has been set once when using TransactionReadonlyAspect AOP annotation:
// TransactionReadonlyAspectTest.java
#RunWith(SpringRunner.class)
#ContextConfiguration(classes = {LoadServiceImpl.class, TransactionReadonlyAspect.class})
public class TransactionReadonlyAspectTest {
#Autowired
private TransactionReadonlyAspect transactionReadonlyAspect;
#MockBean
private LoadServiceImpl loadService;
#Test
public void testReadOnlyTransaction() throws Throwable {
ProceedingJoinPoint mockProceedingJoinPoint = mock(ProceedingJoinPoint.class);
Transactional mockTransactional = mock(Transactional.class);
DatabaseContextHolder spyDatabaseContextHolder = mock(DatabaseContextHolder.class);
when(mockTransactional.readOnly()).thenReturn(true);
when(loadService.findById(16)).thenReturn(null);
when(mockProceedingJoinPoint.proceed()).thenAnswer(invocation -> loadService.findById(16));
transactionReadonlyAspect.proceed(mockProceedingJoinPoint, mockTransactional);
verify(spyDatabaseContextHolder, times(1)).set(DatabaseEnvironment.READONLY); // got the error: Missing method call for verify(mock)
verify(loadService, times(1)).findById(16);
assertEquals(DatabaseContextHolder.getEnvironment(), DatabaseEnvironment.UPDATABLE);
}
}
//TransactionReadonlyAspect.java
#Aspect
#Component
#Order(0)
#Slf4j
public class TransactionReadonlyAspect {
#Around("#annotation(transactional)")
public Object proceed(ProceedingJoinPoint proceedingJoinPoint,
org.springframework.transaction.annotation.Transactional transactional) throws Throwable {
try {
if (transactional.readOnly()) {
log.info("Inside method " + proceedingJoinPoint.getSignature());
DatabaseContextHolder.set(DatabaseEnvironment.READONLY);
}
return proceedingJoinPoint.proceed();
} finally {
DatabaseContextHolder.reset();
}
}
}
// DatabaseContextHolder.java
public class DatabaseContextHolder {
private static final ThreadLocal<DatabaseEnvironment> CONTEXT = new ThreadLocal<>();
public static void set(DatabaseEnvironment databaseEnvironment) {
CONTEXT.set(databaseEnvironment);
}
public static DatabaseEnvironment getEnvironment() {
DatabaseEnvironment context = CONTEXT.get();
System.out.println("context: " + context);
return CONTEXT.get();
}
public static void reset() {
CONTEXT.set(DatabaseEnvironment.UPDATABLE);
}
}
//DatabaseEnvironment.java
public enum DatabaseEnvironment {
UPDATABLE,READONLY
}
// LoadServiceImpl.java
#Service
public class LoadServiceImpl implements LoadService {
#Override
#Transactional(readOnly = true)
public LoadEntity findById(Integer Id) {
return this.loadDAO.findById(Id);
}
...
}
I just want to test DatabaseContextHolder.set(DatabaseEnvironment.READONLY) has been used once then in the TransactionReadonlyAspect finally block it will be reset to DatabaseEnvironment.UPDATABLE which make sense.
However, how to test DatabaseContextHolder.set(DatabaseEnvironment.READONLY) gets called once? Why does this error occur? Is there a better way to test TransactionReadonlyAspect?

How to write integration test of rest api with two threads

what should I use to test a rest api? I want to write integration test with two threads.
I am using Controller->Service->Repository model and want to check if there is any race condition.
I tried with Thread Weaver and something like this but it does not work.
public class MyCounterTests {
private MyCounter counter;
#ThreadedBefore
public void before() {
counter = new MyCounter();
}
#ThreadedMain
public void mainThread() {
counter.increment();
}
#ThreadedSecondary
public void secondThread() {
counter.increment();
}
#ThreadedAfter
public void after() {
assertEquals(2, counter.getCount());
}
#Test
public void testCounter() {
new AnnotatedTestRunner().runTests(this.getClass(), MyCounter.class);
}
}

How do I use a different Spring datasource depending on the name of the unit test?

)
I have a rather unusual requirement for a series of unit tests I'm fixing. Basically, a different datasource/transaction manager needs to be used depending on the method name of the unit test.
For example, if the test name ends with UseDB2, then we use the DB2 data source, if it's UseH2 then we use the H2 datasource.
I thought the way to go about this was to use the AbstractRoutingDatasource provided by the Spring framework.
public class TestRoutingDatasSource extends AbstractRoutingDataSource {
#Override
protected Object determineCurrentLookupKey() {
return DatabaseContextHolder.getDatabaseType();
}
}
Using a context holder to select the required datasource:
public class DatabaseContextHolder {
private static final ThreadLocal<DType> contextHolder = new ThreadLocal<DType>();
public static void setDatabaseType(DType databaseType) {
contextHolder.set(databaseType);
}
public static DType getDatabaseType() {
return (DType) contextHolder.get();
}
public static void clearDatabaseType() {
contextHolder.remove();
}
}
I was then going to use the name of the test to set the context; something like this:
public class MyDBUnitTestCase extends
AbstractTransactionalDataSourceSpringContextTests {
protected DataSource dataSource;
protected String schemaName;
public void setDataSource(DataSource aDataSource) {
this.dataSource = aDataSource;
}
public void setSchemaName(String aSchemaName) {
this.schemaName = aSchemaName;
}
protected void onSetUp() throws Exception {
super.onSetUp();
if (getName().endsWith("UsingDB2")) {
DatabaseContextHolder.setDatabaseType(DType.DB2);
}
else {
DatabaseContextHolder.setDatabaseType(DType.H2);
}
}
But of course, this won't work because by the time I've come to check the name of the test, Spring has already configured all the beans (doh!).
Is there some other mechanism I can use to get this to work?
Thanks very much for your time.

Spring integration test with PowerMockito + TestNG leads to InvocationTargetException

I'm trying to mock a static method with PowerMockito in an integration test with TestNG, but no joy so far.
#PrepareForTest({ HttpCommonClientUtils.class })
public class LiveChannelServiceTestNg extends LiveBaseTestNg {
#Autowired
private LiveChannelShareService liveChannelService;
#Resource(name = "liveSettingService")
private LiveSettingShareService liveSettingService;
#Autowired
private VCloudHelper vcloudHelper;
#ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
static String result = "{\\\"cid\\\":\\\"0aba025de6604ccb931bd9868bddba9a\\\",\\\"duration\\\":120,\\\"format\\\":0,\\\"gmtCreate\\\":1486378732486,\\\"hlsPullUrl\\\":\\\"http://pullhls03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a/playlist.m3u8\\\",\\\"httpPullUrl\\\":\\\"http://flv03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a.flv?netease=flv03f9fed7.live.126.net\\\",\\\"id\\\":1,\\\"name\\\":\\\"直播频道1\\\",\\\"needRecord\\\":1,\\\"pushUrl\\\":\\\"rtmp://p03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a?wsSecret=e5cf3b5c060271fd23ba56469a803a99&wsTime=1486378731\\\",\\\"referType\\\":0,\\\"rtmpPullUrl\\\":\\\"rtmp://v03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a\\\",\\\"status\\\":0,\\\"type\\\":0}";
static String cid = "0aba025de6604ccb931bd9868bddba9a";
#BeforeClass
public void setUp() throws Exception {
/* 公用的环境初始化... */
}
#BeforeMethod
public void testSetUp() throws Exception {
}
#Test
public void test_static() {
String result = "{\"cid\":\"0aba025de6604ccb931bd9868bddba9a\",\"duration\":120,\"format\":0,\"gmtCreate\":1486378732486,\"hlsPullUrl\":\"http://pullhls03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a/playlist.m3u8\",\"httpPullUrl\":\"http://flv03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a.flv?netease=flv03f9fed7.live.126.net\",\"id\":1,\"name\":\"直播频道1\",\"needRecord\":1,\"pushUrl\":\"rtmp://p03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a?wsSecret=e5cf3b5c060271fd23ba56469a803a99&wsTime=1486378731\",\"referType\":0,\"rtmpPullUrl\":\"rtmp://v03f9fed7.live.126.net/live/0aba025de6604ccb931bd9868bddba9a\",\"status\":0,\"type\":0}";
PowerMockito.mockStatic(HttpCommonClientUtils.class);
PowerMockito.when(HttpCommonClientUtils.getHtmlByPostMethod(Matchers.any(HttpClient.class),
Matchers.any(HttpDataProvider.class))).thenReturn(result);
LiveChannelDto dto = liveChannelService.getOrGenerateChannleByBindInfo(0, 1, 101L);
Assert.assertEquals(cid, dto.getCid());
}
When I run this test, a InvocationTargetException is appear

JMeter Plugin - How to Listen to TestState

I am working on developing a JMeter plugin. I'm trying to create an AbstractVisualizer that is capable of monitoring the current test state. However, implementing the TestStateListener doesn't seem to be working.
I'm testing this by creating a basic listener that has a login to output arbitrary info to JMeter's logging console. When a sample is sent through the Add function, a line is sent to the console. But nothing is ever triggered on the various TestState functions. Is there something more structural I'm missing?
public class TestListener extends AbstractVisualizer
implements TestStateListener
{
private static final Logger log = LoggingManager.getLoggerForClass();
#Override
public void add(SampleResult arg0) {
log.info("add");
}
#Override
public void clearData() {
// TODO Auto-generated method stub
}
#Override
public String getStaticLabel()
{
return "Test Listener";
}
#Override
public String getLabelResource() {
return null;
}
#Override
public void testEnded() {
log.info("Test Ended");
}
#Override
public void testEnded(String arg0) {
log.info("Test Ended");
}
#Override
public void testStarted() {
log.info("Test started");
}
#Override
public void testStarted(String arg0) {
log.info("Test started");
}
}
I'm not sure how to do it in 1 class. I have 2 classes:
The UI:
public class MonitorGui extends AbstractListenerGui
{
// ...
#Override
public TestElement createTestElement()
{
TestElement element = new Monitor();// <-- this is the backend
modifyTestElement(element);
return element;
}
// ...
}
And then the backend goes like this:
public class Monitor extends AbstractListenerElement
implements SampleListener,
Clearable, Serializable,
TestStateListener, Remoteable,
NoThreadClone
{
private static final String TEST_IS_LOCAL = "*local*";
// ...
#Override
public void testStarted()
{
testStarted(TEST_IS_LOCAL);
}
#Override
public void testEnded()
{
testEnded(TEST_IS_LOCAL);
}
#Override
public void testStarted(String host)
{
// ...
}
// ...
}
You may not need to implement SampleListener like I do, but probably other things are quite similar.
I based that implementation on a built-in pair of ResultSaverGui and ResultCollector which are the components that are saving results into the file(s) for Simple Data Writer, Summary Report and so on.

Resources