1

我曾嘲笑 HazelcastInstance 及其 IMap。我必须测试几种方法(添加、删除),这些方法使这个 IMap 对象按顺序被锁定、更新、解锁。但是当我尝试运行测试时,Mocked IMap 对象显示为零调用。测试类如下:

@RunWith(PowerMockRunner.class)
public class Test {
    @Mock
    private HazelcastInstance hazelcastInstance;

    @Mock
    private IMap<Object, Object> imap; // but in actual class instead of Object (K, V) 
    // we are having Class Names. private IMap<ClassA,ClassB> imap; 

    private TestClass testClass;

    @Mock
    private ClassA a;

    @Mock
    private ClassB b;

    @Test
    public void testAdd() {
        when(hazelcastInstance.getMap(anyString())).thenReturn(imap);
        testClass.add(a, b);
        verify(imap, times(1)).lock(any()); //supposed to be invoked (1 time). But it is showing as zero interaction
        verify(imap, times(1)).unlock(any());
    }
}

要测试的类如下。

public class TestClass {
    private IMap<ClassA, ClassB> imap = Hazelcast.newHazelcastInstance().getMap("constant);

    public void add(final ClassA key, final ClassB value) {
        if (key == null) {
            return;
        }
        try {
            imap.lock(key);
            imap.put(key, value, 3L, TimeUnit.SECONDS);
        } finally {
            imap.unlock(key);
        }
    }
}
4

3 回答 3

1

在您的情况下,有两个 IMAP 实例。第一个是模拟,第二个是由Hazelcast.newHazelcastInstance(). 问题是TestClass.add()方法使用的是真实的imap,而验证使用的是mock。所以它的交互为零。

您需要使用构造函数或设置器将模拟注入到 TestClass 实例中。

测试示例代码:

@RunWith(PowerMockRunner.class)
public class Test1 {

    @InjectMocks
    private TestClass testClass;

    @Mock
    private IMap<String, Long> imap;

    @Test
    public void testAdd() {
        String key = "a key";
        Long value = 123L;
        testClass.add(key, value);

        verify(imap, times(1)).lock(key);
        verify(imap, times(1)).put(eq(key), eq(value), anyLong(), any(TimeUnit.class));
        verify(imap, times(1)).unlock(key);
    }
}

重构后的TestClass:

class TestClass {
    private IMap<String, Long> imap;

    public TestClass(IMap<String, Long> imap) {
        this.imap = imap;
    }

    public void add(final String key, final Long value) {
        if (key == null) {
            return;
        }
        try {
            imap.lock(key);
            imap.put(key, value, 3L, TimeUnit.SECONDS);
        } finally {
            imap.unlock(key);
        }
    }
}
于 2020-06-04T11:54:24.593 回答
0

问题是你嘲笑

@Mock
 private HazelcastInstance hazelcastInstance;

测试类调用时

Hazelcast.newHazelcastInstance()

在测试类中显示架构问题。将映射注入 TestClass 的最佳方式 - 传入构造函数参数。

public class TestClass {
    private final IMap<ClassA, ClassB> imap;

    public TestClass(IMap<ClassA, ClassB> imap) {
        this.imap = imap;
    }

现在您可以创建 TestClass 的实例

IMap imap = mock(IMap.class)    
testClass = new TestClass(imap)
于 2016-07-30T07:21:07.933 回答
0

创建自己的 imap 测试类并实现这样的方法

公共类 HazelcastMap 实现 IMap
{


    私有地图 map = new HashMap();

    @覆盖
    公共无效putAll(地图m){

    }

    @覆盖
    公共整数大小(){
        返回0;
    }

    @覆盖
    公共布尔 isEmpty() {
        返回假;
    }

    @覆盖
    公共布尔包含键(对象键){
        返回 map.containsKey(key);
    }

    @覆盖
    公共布尔包含值(对象值){
        返回假;
    }

    @覆盖
    公共对象获取(对象键){
        返回 map.get(key);
    }

    @覆盖
    公共对象放置(对象键,对象值){
        map.put(键,值);
        返回值;
    }

    @覆盖
    公共对象删除(对象键){
        返回空值;
    }

    @覆盖
    公共布尔删除(对象键,对象值){
        返回假;
    }

    @覆盖
    公共无效removeAll(谓词谓词){

    }

    @覆盖
    公共无效删除(对象键){

    }

    @覆盖
    公共无效冲洗(){

    }

    @覆盖
    公共地图getAll(设置密钥){
        返回地图;
    }

    @覆盖
    公共无效负载(布尔替换现有值){

    }

    @覆盖
    公共无效loadAll(设置键,布尔replaceExistingValues){

    }

    @覆盖
    公共无效清除(){

    }

    @覆盖
    公共 ICompletableFuture getAsync(对象键){
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture putAsync(对象键,对象值){
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture putAsync(对象键,对象值,长 ttl,TimeUnit ttlUnit){
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture putAsync(对象键,对象值,长 ttl,TimeUnit ttlUnit,长 maxIdle,
        TimeUnit maxIdleUnit) {
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture setAsync(对象键,对象值){
        返回空值;
    }

    @覆盖
    public ICompletableFuture setAsync(Object key, Object value, long ttl, TimeUnit ttlUnit) {
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture setAsync(对象键,对象值,长 ttl,TimeUnit ttlUnit,长 maxIdle,
        TimeUnit maxIdleUnit) {
        返回空值;
    }

    @覆盖
    公共 ICompletableFuture removeAsync(对象键){
        返回空值;
    }

    @覆盖
    public boolean tryRemove(Object key, long timeout, TimeUnit timeunit) {
        返回假;
    }

    @覆盖
    public boolean tryPut(Object key, Object value, long timeout, TimeUnit timeunit) {
        返回假;
    }

    @覆盖
    public Object put(Object key, Object value, long ttl, TimeUnit ttlUnit) {
        返回空值;
    }

    @覆盖
    public Object put(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle, TimeUnit maxIdleUnit) {
        返回空值;
    }

    @覆盖
    public void putTransient(Object key, Object value, long ttl, TimeUnit ttlUnit) {

    }

    @覆盖
    public void putTransient(对象键,对象值,长 ttl,TimeUnit ttlUnit,长 maxIdle,TimeUnit maxIdleUnit){

    }

    @覆盖
    公共对象 putIfAbsent(对象键,对象值){
        返回空值;
    }

    @覆盖
    public Object putIfAbsent(Object key, Object value, long ttl, TimeUnit ttlUnit) {
        返回空值;
    }

    @覆盖
    public Object putIfAbsent(Object key, Object value, long ttl, TimeUnit ttlUnit, long maxIdle,
        TimeUnit maxIdleUnit) {
        返回空值;
    }

    @覆盖
    公共布尔替换(对象键,对象旧值,对象新值){
        返回假;
    }

    @覆盖
    公共对象替换(对象键,对象值){
        返回空值;
    }

    @覆盖
    公共无效集(对象键,对象值){

    }

    @覆盖
    public void set(Object key, Object value, long ttl, TimeUnit ttlUnit) {

    }

    @覆盖
    公共无效集(对象键,对象值,长ttl,TimeUnit ttlUnit,长maxIdle,TimeUnit maxIdleUnit){

    }

    @覆盖
    公共无效锁(对象键){

    }

    @覆盖
    公共无效锁(对象键,长租期,TimeUnit timeUnit){

    }

    @覆盖
    公共布尔isLocked(对象键){
        返回假;
    }

    @覆盖
    公共布尔tryLock(对象键){
        返回假;
    }

    @覆盖
    public boolean tryLock(Object key, long time, TimeUnit timeunit) throws InterruptedException {
        返回假;
    }

    @覆盖
    public boolean tryLock(Object key, long time, TimeUnit timeunit, long leaseTime, TimeUnit leaseTimeunit)
        抛出 InterruptedException {
        返回假;
    }

    @覆盖
    公共无效解锁(对象密钥){

    }

    @覆盖
    公共无效力解锁(对象键){

    }

    @覆盖
    公共字符串 addLocalEntryListener(MapListener 监听器) {
        返回空值;
    }

    @覆盖
    公共字符串 addLocalEntryListener(EntryListener 监听器) {
        返回空值;
    }

    @覆盖
    public String addLocalEntryListener(MapListener listener, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addLocalEntryListener(EntryListener listener, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addLocalEntryListener(MapListener listener, Predicate predicate, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addLocalEntryListener(EntryListener listener, Predicate predicate, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    公共字符串 addInterceptor(MapInterceptor 拦截器) {
        返回空值;
    }

    @覆盖
    公共无效removeInterceptor(字符串ID){

    }

    @覆盖
    public String addEntryListener(MapListener listener, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(EntryListener listener, boolean includeValue) {
        返回空值;
    }

    @覆盖
    公共布尔removeEntryListener(字符串ID){
        返回假;
    }

    @覆盖
    公共字符串 addPartitionLostListener(MapPartitionLostListener 监听器){
        返回空值;
    }

    @覆盖
    public boolean removePartitionLostListener(String id) {
        返回假;
    }

    @覆盖
    public String addEntryListener(MapListener listener, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(EntryListener listener, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(MapListener listener, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(EntryListener listener, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(MapListener listener, Predicate predicate, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public String addEntryListener(EntryListener listener, Predicate predicate, Object key, boolean includeValue) {
        返回空值;
    }

    @覆盖
    公共EntryView getEntryView(对象键){
        返回空值;
    }

    @覆盖
    公共布尔驱逐(对象键){
        返回假;
    }

    @覆盖
    公共无效 evictAll() {

    }

    @覆盖
    公共设置密钥集(){
        返回空值;
    }

    @覆盖
    公共集合值(){
        返回空值;
    }

    @覆盖
    公共设置 entrySet() {
        返回空值;
    }

    @覆盖
    公共设置密钥集(谓词谓词){
        返回空值;
    }

    @覆盖
    公共集entrySet(谓词谓词){
        返回空值;
    }

    @覆盖
    公共集合值(谓词谓词){
        返回空值;
    }

    @覆盖
    公共设置 localKeySet() {
        返回空值;
    }

    @覆盖
    公共设置localKeySet(谓词谓词){
        返回空值;
    }

    @覆盖
    public void addIndex(字符串属性,布尔排序){

    }

    @覆盖
    公共 LocalMapStats getLocalMapStats() {
        返回空值;
    }

    @覆盖
    public Object executeOnKey(Object key, EntryProcessor entryProcessor) {
        返回空值;
    }

    @覆盖
    public Map executeOnKeys(Set keys, EntryProcessor entryProcessor) {
        返回空值;
    }

    @覆盖
    public void submitToKey(对象键,EntryProcessor entryProcessor,ExecutionCallback 回调){

    }

    @覆盖
    公共 ICompletableFuture submitToKey(对象键,EntryProcessor entryProcessor){
        返回空值;
    }

    @覆盖
    公共地图 executeOnEntries(EntryProcessor entryProcessor) {
        返回空值;
    }

    @覆盖
    public Map executeOnEntries(EntryProcessor entryProcessor, Predicate predicate) {
        返回空值;
    }

    @覆盖
    公共查询缓存getQueryCache(字符串名称){
        返回空值;
    }

    @覆盖
    public QueryCache getQueryCache(String name, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public QueryCache getQueryCache(String name, MapListener listener, Predicate predicate, boolean includeValue) {
        返回空值;
    }

    @覆盖
    public boolean setTtl(Object key, long ttl, TimeUnit timeunit) {
        返回假;
    }

    @覆盖
    公共对象聚合(供应商供应商,聚合聚合,JobTracker jobTracker){
        返回空值;
    }

    @覆盖
    公共对象聚合(供应商供应商,聚合聚合){
        返回空值;
    }

    @覆盖
    公共集合项目(投影投影,谓词谓词){
        返回空值;
    }

    @覆盖
    公共收藏项目(投影投影){
        返回空值;
    }

    @覆盖
    公共对象聚合(聚合器聚合器,谓词谓词){
        返回空值;
    }

    @覆盖
    公共对象聚合(聚合器聚合器){
        返回空值;
    }

    @覆盖
    公共字符串 getPartitionKey() {
        返回空值;
    }

    @覆盖
    公共字符串 getName() {
        返回空值;
    }

    @覆盖
    公共字符串 getServiceName() {
        返回空值;
    }

    @覆盖
    公共无效销毁(){

    }
}
于 2020-05-17T18:45:20.410 回答